Behavioral results. Let’s look at how participants performed in the task

#house keeping
rm(list=ls())
#load packages
packages <- c('dplyr','cowplot', 'Rmisc', 'ggbeeswarm', 'brms', 'WRS2', 'BayesFactor','scales',  'plyr', 'reshape2', 'ggridges', 'ggplot2', 'jsonlite', 'MASS', 'gridExtra', 'Hmisc', 'lsr', 'pander', 'ggsignif', 'rstatix', 'sjstats', 'emmeans')
invisible(lapply(packages, require, character.only = TRUE))

theme_set(theme_cowplot(font_size=12))
source('../dataProcessing.R') 
source('../statisticalTests.R')
#Wrapper for brm models such that it saves the full model the first time it is run, otherwise it loads it from disk
run_model <- function(expr, modelName, path='../brmsModels', reuse = TRUE) {
  path <- paste0(path,'/', modelName, ".brm")
  if (reuse) {
    fit <- suppressWarnings(try(readRDS(path), silent = TRUE))
  }
  if (is(fit, "try-error")) {
    fit <- eval(expr)
    saveRDS(fit, file = path)
  }
  fit
}

First, let’s load the data. These data import functions are defined in dataProcessing.R where I convert the raw data into a usuable dataframe.

dataDir <- '../experimentData/full.csv' #
df <- dataImport(dataFile = dataDir ,normalize=F) #These two functions are defined in `dataProcessing.R`
trajDF <- importTrajData(dataFile = dataDir,normalize=F)
#Trim last rounds
df<- subset(df, round<10) #Last round is the bonus round and is not included in the behavioral analysis, since the judgment task may bias subsequent performance

n_rounds = 9 #without bonus round
n_trials = 20 #per round

Demographics

[1] "Participants: 129"
[1] "Age: 14.94574 ± 8.724346"
[1] "Males: 74"
[1] "Earnings :15.6496899224806 USD ± 0.9952732"
[1] "Task Duration: 54.15182 mins ± 18.7926"
[1] "Gap between tasks: 18.2791 hours ± 8.555568"

Training Phase

Before the main bandit task, participants performed a training phase where they were required to match a target stimuli until a learning criterion was met (at least 32 trials and a run of 9 out of 10 correct). The task used the same stimuli and inputs as the main bandit task, and was used to familiarize participants and have them achieve a similar level of fluency with both spatial and conceptual domains. Let’s first look at some of the results.

Participants had a lower accuracy on the conceptual training (\(t(128)=7.5\), \(p<.001\), \(d=0.8\), \(BF>100\)) and required more trials to reach the training criterion (\(Z=-4.1\), \(p<.001\), \(r=-.40\), \(BF>100\)), which is to be expected since it is intuitively more difficult.

#Overall Correct choices
dat <- ddply(df, ~id+context, plyr::summarize, trajCorrect = mean(trajCorrect), trajAvgSteps = mean(trajAvgSteps))
trajp1a<- ggplot(dat, aes(x = context, y = trajCorrect, color = context))+
  geom_line(aes(group=id),color = 'black', alpha = 0.1)+
  geom_boxplot(outlier.shape = NA, fill=NA, color = 'black', width = 0.1)+
  geom_quasirandom(alpha = 0.7)+
  stat_summary(fun.y=mean, geom='point', shape=23, color = 'black', size =3)+
  ylab('P(correct)')+
  xlab('')+
  scale_color_brewer(palette = "Dark2", name = "") +
  theme(legend.position='none')
trajp1a


#Trials until complete
dat <- ddply(trajDF, ~id+context, plyr::summarize, trajTrials = max(trial))
#ttestPretty(subset(dat, context == 'Spatial')$trajTrials, subset(dat, context == 'Conceptual')$trajTrials, paired=T) #Data doesn't look very normal
#ranktestPretty(subset(dat, context == 'Spatial')$trajTrials, subset(dat, context == 'Conceptual')$trajTrials, paired=T) #Is there a meaninful difference in the number of trials needed to finish the training phase? #Note sometimes Bayes Factors display as NA when they are very large

trajComplete <- ggplot(dat, aes(x = context, y = trajTrials, color = context))+
  geom_line(aes(group=id),color = 'black', alpha = 0.1)+
  geom_quasirandom( alpha = 0.6)+
  geom_boxplot(color='black', fill= NA, width =.2, outlier.shape = NA)+
  stat_summary(fun.y = mean, geom='point', shape = 23,size=3, color = 'black')+
  geom_hline(yintercept = 32, linetype = 'dashed')+
  scale_color_brewer(palette = "Dark2", name = "") +
  ylab('Trials Until Complete')+
  xlab('')+
  #coord_cartesian(ylim=c(30,128), )+
  scale_y_continuous(breaks=c(32,64, 96, 128), limits = c(32,128))+
  theme(legend.position = 'none')
trajComplete

We can also look at the magnitude of errors vs. the frequenvy of occurence, which gives us a nice Shepard (1987) style generalization gradient.

#Magnitude of error vs. frequency
gradientDF <- ddply(trajDF, ~context+manhattanError,plyr::summarize, counts = table(manhattanError)) 
#Normalize into a percentage
gradientDF[gradientDF$context == 'Conceptual','P'] <- gradientDF[gradientDF$context == 'Conceptual','counts']/sum(gradientDF[gradientDF$context == 'Conceptual','counts'])
gradientDF[gradientDF$context == 'Spatial','P'] <- gradientDF[gradientDF$context == 'Spatial','counts']/sum(gradientDF[gradientDF$context == 'Spatial','counts'])

pError<- ggplot(gradientDF, aes(x = manhattanError, y = P, color = context, shape = context))+
  geom_line()+
  geom_point()+
  coord_cartesian(xlim=c(0,5))+
  ylab('P(error)')+
  xlab('Magnitude of Error (Manhattan distance)')+
  scale_color_brewer(palette = "Dark2", name = "Task")+
  scale_shape_manual( values = c(16,15),name = "Task")+
  theme(legend.position=c(1,1), legend.justification = c(1,1))

pError

How did accuracy differ for the different options?


spatialCounts <- ddply(subset(trajDF, context == 'Spatial'), .(x, y), plyr::summarize, correct = sum(trajCorrect)/length(trajCorrect))
names(spatialCounts) <- c("X", "Y", "Accuracy")
spatialCounts$task <- 'Spatial'

conceptCounts <- ddply(subset(df, context == 'Conceptual'), .(x, y), plyr::summarize, correct = sum(trajCorrect)/length(trajCorrect))
names(conceptCounts) <- c("X", "Y", "Accuracy")
conceptCounts$task <- 'Conceptual'

trainingAccuracyDF <-rbind(spatialCounts, conceptCounts)
trajheatmap<- ggplot(trainingAccuracyDF, aes(x=X, y = Y, fill=Accuracy)) +
  geom_tile()+
  scale_fill_distiller(palette = "Spectral", name = 'P(correct)',limits = c(0,1),labels = scales::percent_format(accuracy = 1))+
  theme_classic() +
  facet_grid(~task)+
  coord_equal() +
  theme(strip.background=element_blank(), legend.key=element_rect(color=NA), axis.line=element_blank(),axis.text.x=element_blank(),
        axis.text.y=element_blank(),axis.ticks=element_blank(), panel.background=element_blank(),panel.border=element_blank(),panel.grid.major=element_blank(),
        panel.grid.minor=element_blank(),plot.background=element_blank())+
  labs(x = '', y = '')
trajheatmap

Performance

Now let’s finally look at performance on the bandit task.

#Construct plotting dataframes
meanDF <- ddply(df, .(id, context, environment, contextOrder), plyr::summarize, meanScore = mean(z))
conceptualScores <- subset(meanDF, context == "Conceptual")
spatialScores <- subset(meanDF, context == "Spatial")
mergedDF <- merge(conceptualScores, spatialScores, by ="id")
joinedDF <- rbind(conceptualScores, spatialScores)
bothTasksDF <- ddply(joinedDF, .(id, environment, contextOrder), plyr::summarize, meanScore = mean(meanScore))
randomDF <- read.csv("../rationalModels/random.csv") #load random model

joinedDF$contextOrder <- factor(joinedDF$contextOrder)
levels(joinedDF$contextOrder)<- c("Spatial First", "Conceptual First")

Overall, participants performed far better than chance in both Conceptual (\(t(128)=24.6\), \(p<.001\), \(d=2.2\), \(BF>100\)) and Spatial tasks (\(t(128)=34.6\), \(p<.001\), \(d=3.0\), \(BF>100\)). Let’s now do a two way mixed ANOVA to see how our context x environment design influenced performance.

#Two way mixed ANOVA: context is within, environment is between 
dd<-ddply(rbind(conceptualScores, spatialScores), ~id+context+environment, summarise, m=mean(meanScore))
dd$id <- factor(dd$id)
res.aov <- aov(m ~ environment*context + Error(id/context), data=dd)
anova_stats(res.aov)
# Now let's replicate via Robust ANOVA
bwtrim(m ~ environment*context, id = id, data=dd, tr = 0.2) #using 20% trimmed means
Call:
bwtrim(formula = m ~ environment * context, id = id, data = dd, 
    tr = 0.2)
sppba(m ~ environment*context, id = id, data=dd) #Main fixed effect
Call:
sppba(formula = m ~ environment * context, id = id, data = dd)

Test statistics:
[1] -6.345

Test whether the corrresponding population parameters are the same:
p-value: 0.002 
sppbb(m ~ environment*context, id = id, data=dd) #Within-subect effect
Call:
sppbb(formula = m ~ environment * context, id = id, data = dd)

Test statistics:
[1] -4.828

Test whether the corrresponding population parameters are the same:
p-value: 0 
#Now compute Bayes factor
invisible(bf <- anovaBF(m ~ environment*context+id,  data=dd,  whichRandom="id"))

  |                                                                                                                                             
  |                                                                                                                                       |   0%
  |                                                                                                                                             
  |===========================                                                                                                            |  20%
  |                                                                                                                                             
  |======================================================                                                                                 |  40%
  |                                                                                                                                             
  |=================================================================================                                                      |  60%
  |                                                                                                                                             
  |============================================================================================================                           |  80%
  |                                                                                                                                             
  |=======================================================================================================================================| 100%
bf
Bayes factor analysis
--------------
[1] context + id                                     : 455178   ±1.03%
[2] environment + id                                 : 13.06263 ±1.43%
[3] context + environment + id                       : 6293695  ±2.35%
[4] context + environment + context:environment + id : 2376791  ±2.28%

Against denominator:
  m ~ id 
---
Bayes factor type: BFlinearModel, JZS

Looks like strong evidence for differences.

#Mean performance plots
p1a <- ggplot(joinedDF, aes(x = interaction(context, environment), y = meanScore, color = context))+
  geom_boxplot(fill=NA, color = 'black', outlier.shape=NA, width = 0.2)+
  geom_line(aes(group=id), color = 'black', alpha = 0.1)+
  geom_quasirandom(alpha = 0.7)+
  geom_hline(yintercept = mean(randomDF$meanReward), color = 'black', linetype = 'dashed')+
  stat_summary(fun.y = mean, shape = 23, geom='point', size = 3, fill = NA, color ='black')+
  #facet_grid(~environment)+
  ylab("Mean Reward \u00B1SE")+
  xlab('')+
  annotate('text', x = 1.5, y = 110, label='Rough')+
  annotate('text', x = 3.5, y = 110, label='Smooth')+
  scale_x_discrete(labels=c("Conceptual", "Spatial", "Conceptual", "Spatial"))+
  scale_color_brewer(palette = "Dark2", name = "") +
  scale_fill_brewer(palette = "Dark2", name = "") +
  geom_signif(y_position = c(95, 97, 103),  xmin = c(1,3, 1.5), xmax = c(2,4, 3.5), annotation = c("BF>100","BF = 14", "BF = 12"), color = 'black')+
  #geom_signif(comparisons=list( c("Conceptual", "Spatial"), c("Conceptual", "Spatial")), annotations=c("",""), col="black")+ # 
  theme(text = element_text(size=12,  family="sans"),strip.background=element_blank(), legend.key=element_rect(color=NA), legend.position='None')
p1a

Participants earned higher rewards in the Spatial than the Conceptual task (one sample \(t\)-test: \(t(128)=-6.0\), \(p<.001\), \(d=0.5\), \(BF>100\)) and better in smooth than in rough environments (two sample \(t\)-test: \(t(127)=3.1\), \(p=.003\), \(d=0.5\), \(BF=12\)). We also find correlated performance between tasks (\(r=.53\), \(p<.001\), \(BF>100\)).

#statistical tests
ttestPretty(conceptualScores$meanScore, mu=mean(randomDF$meanReward)) #compared to chance
ttestPretty(spatialScores$meanScore, mu=mean(randomDF$meanReward))

#T-tests
ttestPretty(conceptualScores$meanScore, spatialScores$meanScore, var.equal = TRUE, paired=T) #context
ttestPretty(subset(bothTasksDF, environment=="Smooth")$meanScore, subset(bothTasksDF, environment=="Rough")$meanScore, var.equal = TRUE) #environment
corTestPretty(conceptualScores$meanScore, spatialScores$meanScore) #correlated performance
ttestPretty(subset(conceptualScores, environment=='Smooth')$meanScore, subset(spatialScores, environment=="Smooth")$meanScore, var.equal = TRUE, paired=T) #context
ttestPretty(subset(conceptualScores, environment=='Rough')$meanScore, subset(spatialScores, environment=="Rough")$meanScore, var.equal = TRUE, paired=T, maxBF = Inf) #context

Correlation between tasks:

#corTestPretty(conceptualScores$meanScore, spatialScores$meanScore)
p1b <- ggplot(mergedDF, aes(x=meanScore.x, y = meanScore.y, color = environment.x, shape= environment.x)) +
  geom_abline(slope=1, intercept=0, linetype='dashed') +
  geom_point(alpha=0.9, size = 2.5)+
  ylab('Spatial Reward')+
  xlab('Conceptual Reward')+
  xlim(40,100)+
  ylim(40,100) +
  annotate("text", x = 50, y = 95, label = "'r = .53' *','* ~~'BF > 100'", parse=TRUE, size=5, family="sans") +
  theme(legend.position=c(1,0),legend.justification=c(1,0), strip.background=element_blank(), legend.key=element_rect(color=NA), text = element_text(size=12,  family="sans"))+
  #scale_color_rickandmorty(name="Environment", palette = "schwifty")+
  scale_color_manual(name="Environment", values=c("#24325FFF", '#B7E4F9FF'))+
  scale_shape_manual(name="Environment", values= c(17,16))
p1b

Order effect

We find an interesting one-directional order effect. Participants performed better on the conceptual task once they had experience with the spatial task (\(t(127)=2.8\), \(p=.006\), \(d=0.5\), \(BF=6.4\). This was not the case for the spatial task, where performance did not differ if performed first or second (\(t(127)=-1.7\), \(p=.096\), \(d=0.3\), \(BF=.67\)). Thus, experience with spatial search boosted performance on conceptual search, but not vice versa.

df$FirstTask <- ifelse(df$contextOrder==0, 'Spatial First', 'Conceptual First') #which task was performed first?
df$taskOrder <- ifelse((df$FirstTask=="Spatial First" & df$context == "Spatial") |(df$FirstTask=="Conceptual First" & df$context == "Conceptual"), 1, 2 ) 
df$FirstTask <- factor(df$FirstTask, levels = c("Conceptual First","Spatial First"))
orderDF <- ddply(df, .(id, context, environment, FirstTask, taskOrder), plyr::summarize, meanScore = mean(z))

pOrder <- ggplot(orderDF, aes(x = interaction(context,FirstTask), y = meanScore, fill = context, color = context))+
  geom_boxplot( color = 'black', position = position_dodge(width = 1), outlier.shape=NA, width = 0.2, alpha =0)+
  geom_quasirandom(alpha = 0.7, dodge.width = 1)+
  #geom_line(aes(group=id), color = 'black', alpha = 0.1)+
  stat_summary(fun.y = mean, shape = 23, geom='point', size = 3, position = position_dodge(width = 1), color ='black', fill = NA)+
  #stat_summary(fun.y=mean, geom='bar', position = position_dodge(width = 1), color='black')+
  #stat_summary(fun.data = mean_cl_boot, geom='errorbar', color='black', position = position_dodge(width = 1), width = .2)+
  scale_fill_brewer(palette = 'Dark2', name= 'Task')+
  scale_color_brewer(palette = 'Dark2', name= 'Task')+
  annotate('text', x = 1.5, y = 118, label='Conceptual First')+
  annotate('text', x = 3.5, y = 118, label='Spatial First')+
  scale_x_discrete(labels=c("Conceptual", "Spatial", "Conceptual", "Spatial"))+
  geom_hline(yintercept = mean(randomDF$meanReward), color = 'black', linetype = 'dashed')+
  #coord_cartesian(ylim =c(40,120))+
  xlab('')+
  ylab('Mean Reward ±SE')+
  geom_signif(y_position = c(100, 108),  xmin = c(1,2), xmax = c(3,4), annotation = c("BF=6.4","BF=0.67"), color = 'black')+
  #theme(legend.position=c(0.05,1), legend.justification = c(0,1), legend.direction='horizontal')
  theme(legend.position='none')
pOrder

Learning over trials and rounds

Participants improved strongly over trials (Pearson correlation between score and trial number: \(r=.88\), \(p<.001\), \(BF>100\)) and to a lesser extent over rounds (\(r=.81\), \(p=.008\), \(BF=5.1\)).

#Mean score over trial
trialDF <- ddply(df, .(id, context, environment, trial), plyr::summarize, meanScore=mean(z))
randomDF <- read.csv("../rationalModels/random.csv") #load random model

p3a <- ggplot(trialDF, aes(x=trial, y = meanScore, color = context)) +
  stat_summary(fun.y = mean, geom = 'line')+
  stat_summary(fun.data = mean_se,aes ( fill=context), geom = 'ribbon', alpha = 0.7, color=NA) +
  stat_summary(data = randomDF, aes(x=trial, y = meanReward), fun.y = mean, geom='line', color = 'black', fill=NA, linetype = 'dashed')+
  #geom_hline(yintercept =  50, linetype = 'dashed', color = 'black')+
  facet_grid(~environment)+
  scale_fill_brewer(palette = "Dark2", name="Task" ) +
  scale_color_brewer(palette = "Dark2", name="Task") +
  #coord_cartesian(ylim=c(49,95))+
  ylab("Mean Reward \u00B1SE") + 
  scale_x_continuous(breaks = round(seq(0,20, by = 5),1))+
  xlab("Trial")+
  theme(legend.position=c(1, 0.15), legend.justification=c(1,0), strip.background=element_blank(), legend.key=element_blank(), legend.background=element_blank())
Ignoring unknown parameters: fill
p3a


#Mean score over round
roundDF <- ddply(df, .(id, context, environment, round), plyr::summarize, meanScore=mean(z))

pRound <- ggplot(roundDF, aes(x=round, y = meanScore, color = context )) +
  stat_summary(fun.y = mean, geom = 'line')+
  stat_summary(fun.data = mean_se,aes(fill=context), geom = 'ribbon', alpha = 0.7, color=NA) +
  stat_summary(data = randomDF, aes(x=trial, y = meanReward), fun.y = mean, geom='line', color = 'black', fill=NA, linetype = 'dashed')+
  coord_cartesian(xlim=c(0,9))+
  facet_grid(~environment)+
  scale_fill_brewer(palette = "Dark2", name="Task") +
  scale_color_brewer(palette = "Dark2", name="Task") +
  ylab("Mean Reward \u00B1SE") + 
  scale_x_continuous(breaks = round(seq(0,9, by = 2),1))+
  #coord_cartesian(ylim=c(20,50))+
  xlab("Round")+
  theme(legend.position=c(0.05, 0.1), legend.justification=c(0,0), strip.background=element_blank(), legend.background=element_blank(), legend.key=element_rect(color=NA))
Ignoring unknown parameters: fill
pRound

Heatmap of clicks

Let’s look at any patterns in how people searched the input space. Unsurprisingly, there is a preference for corners and edges. Yellow is mapped to random chance, so orange and red are higher than chance, while green and blue are lower than chance.

#Heatmap of clicks
#spatial and spatial
spatialCounts <- ddply(subset(df, context == 'Spatial'), .(x, y), nrow)
names(spatialCounts) <- c("X", "Y", "Freq")
spatialCounts$Prob <- spatialCounts$Freq / sum(spatialCounts$Freq)

conceptCounts <- ddply(subset(df, context == 'Conceptual'), .(x, y), nrow)
names(conceptCounts) <- c("X", "Y", "Freq")
conceptCounts$Prob <- conceptCounts$Freq / sum(conceptCounts$Freq)

maxFreq <- max(max(spatialCounts$Prob), max(conceptCounts$Prob))

heatmapSpatial <- ggplot(spatialCounts, aes(x=X, y = Y, fill=Prob)) +
  geom_tile()+
  scale_fill_distiller(palette = "Spectral", name = 'Freq', values=rescale(c(0,1/64,maxFreq)),limits = c(0,maxFreq),labels = scales::percent_format(accuracy = 1))+
  theme_classic() +
  coord_equal() +
  theme(strip.background=element_blank(), legend.key=element_rect(color=NA), axis.line=element_blank(),axis.text.x=element_blank(),
        axis.text.y=element_blank(),axis.ticks=element_blank(), panel.background=element_blank(),panel.border=element_blank(),panel.grid.major=element_blank(),
        panel.grid.minor=element_blank(),plot.background=element_blank())+
  ggtitle('Spatial Heatmap')
heatmapSpatial


conceptualHeatmap <- ggplot(conceptCounts, aes(x=X, y = Y, fill=Prob)) +
  geom_tile()+
  scale_fill_distiller(palette = "Spectral",name = 'Freq', values=rescale(c(0,1/64,maxFreq)), limits = c(0,maxFreq),labels = scales::percent_format(accuracy = 1))+
  theme_classic() +
  xlab('Rotation')+
  ylab('Stripes')+
  coord_equal() +
  theme(strip.background=element_blank(), legend.key=element_rect(color=NA), axis.line=element_blank(),axis.text.x=element_blank(),
        axis.text.y=element_blank(),axis.ticks=element_blank(), panel.background=element_blank(),panel.border=element_blank(),panel.grid.major=element_blank(),
        panel.grid.minor=element_blank(),plot.background=element_blank())+
  ggtitle('Conceptual Heatmap')
conceptualHeatmap

Reaction times

We can also analyze participant reaction times. Participants were slower in the conceptual task (\(t(128)=8.3\), \(p<.001\), \(d=0.7\), \(BF>100\)), but there were no differences across environments (\(t(256)=0.7\), \(p=.502\), \(d=0.08\), \(BF=.17\)).

#Individual participant quartile splits
df$prevRewardValue <- NA
for (pid in unique(df$id)){
  subd <- subset(df, id==pid)
  xs <- quantile(subd$previousReward, probs=0:4/4, na.rm = T)
  df[df$id==pid,'prevRewardValue'] <- cut(subd$previousReward, breaks=xs,labels=c("Q1", "Q2", "Q3", "Q4") )
}

df$prevRewardValue <- factor(df$prevRewardValue)
levels(df$prevRewardValue) <- c("Q1", "Q2", "Q3", "Q4")
colfunc<-colorRampPalette(c("#0D0887FF", "#CC4678FF", "#F0F921FF"))
p11 <- ggplot(subset(df, ts>0 & !is.na(prevRewardValue)), aes(x=ts/1000, y=prevRewardValue, fill = prevRewardValue))+
  geom_density_ridges()+
  xlab('RT in seconds (log scale)')+
  scale_color_manual(values = colfunc(5), name="")+
  scale_fill_manual(values = colfunc(5), name="")+
  scale_x_log10()+
  annotation_logticks(sides='b')+
  facet_grid(~context, labeller = as_labeller(contextLabels))+
  coord_cartesian(xlim = c(0.1,50))+
  theme_classic()+
  scale_y_discrete(expand = c(0.01, 0))+
  theme(legend.position='none', strip.background=element_blank(), legend.key=element_rect(color=NA))+
  ylab('Previous Reward')
p11

There doesn’t seem to be any connection between reaction time and previous reward value. It seems like any influence of deliberation on reaction time is likely washed out by larger influence of trajectory length.

ggplot(subset(df,steps<=20), aes(x =steps,  y = log(ts/1000), color = context, fill = context))+
  #geom_smooth(fill=NA)+
  stat_summary(fun.y = mean, geom = "point") + 
  stat_summary(fun.data = mean_cl_boot, geom = "errorbar") +
  #coord_cartesian(xlim=c(0,20), ylim=c(4,10)) + #Tukey outlier criterion indicates outliers above 20; min(boxplot.stats(df$steps)$out)
  #facet_grid(~environment)+
  scale_fill_brewer(palette = "Dark2", name="Task") +
  scale_color_brewer(palette = "Dark2", name="Task") +
  theme(legend.position=c(0.05,1),legend.justification = c(0,1), strip.background=element_blank(), legend.background=element_blank(), legend.key=element_rect(color=NA))+
  ylab("RT in seconds (log scale)")+
  xlab('Trajectory Length')+
  scale_y_log10()+
  annotation_logticks(sides='l')

Final Plots

Main text

#completeplot <- plot_grid(p3a, p1b, p4alt, trajectoryplot, pGeneralization, p5,conceptualHeatmap, heatmapSpatial , ncol=2, labels = "auto")
completeplot <- cowplot::plot_grid(p1a, p1b, pOrder ,p3a,  p4alt, p5alt, ncol=2, labels = "auto")
Removed 1 rows containing non-finite values (stat_density).Removed 4966 rows containing non-finite values (stat_summary).
completeplot


ggsave('../plots/behavioralplot.pdf',completeplot, width = 10, height = 8, unit='in', useDingbats=F)

SI


#SI plots
trainingRound <- cowplot::plot_grid(trajComplete, trajp1a, trajheatmap, pError,  ncol=2, labels = 'auto')
trainingRound

ggsave(filename = '../plots/TrainingPlots.pdf', trainingRound, width = 9,height = 6, units = 'in', useDingbats=FALSE)
trajectoryPlots <- cowplot::plot_grid(trajectoryplot,pTrajLengthReward,p6, inputdir,pAttentionTaskOrder, pScoreAttention,  ncol=3, labels="auto")
Removed 843 rows containing non-finite values (stat_bin).Removed 8 rows containing missing values (geom_bar).Removed 7288 rows containing non-finite values (stat_summary).
trajectoryPlots

ggsave(filename = '../plots/TrajectoryPlots.pdf', trajectoryPlots, width = 12,height = 6, units = 'in', useDingbats=FALSE)


pAttentionTaskOrder


heatmaps <- cowplot::plot_grid(conceptualHeatmap, heatmapSpatial, labels = "auto")
heatmaps
ggsave(filename = '../plots/heatmaps.pdf', heatmaps, width = 8,height = 4, units = 'in', useDingbats=FALSE)
LS0tCnRpdGxlOiAiQmVoYXZpb3JhbCBSZXN1bHRzIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAogICAgdG9jOiB5ZXMKICAgIGNvZGVfZm9sZGluZzogaGlkZQogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwotLS0KCkJlaGF2aW9yYWwgcmVzdWx0cy4gTGV0J3MgbG9vayBhdCBob3cgcGFydGljaXBhbnRzIHBlcmZvcm1lZCBpbiB0aGUgdGFzawoKYGBge3IgbWVzc2FnZT1GQUxTRX0KI2hvdXNlIGtlZXBpbmcKcm0obGlzdD1scygpKQojbG9hZCBwYWNrYWdlcwpwYWNrYWdlcyA8LSBjKCdkcGx5cicsJ2Nvd3Bsb3QnLCAnUm1pc2MnLCAnZ2diZWVzd2FybScsICdicm1zJywgJ1dSUzInLCAnQmF5ZXNGYWN0b3InLCdzY2FsZXMnLCAgJ3BseXInLCAncmVzaGFwZTInLCAnZ2dyaWRnZXMnLCAnZ2dwbG90MicsICdqc29ubGl0ZScsICdNQVNTJywgJ2dyaWRFeHRyYScsICdIbWlzYycsICdsc3InLCAncGFuZGVyJywgJ2dnc2lnbmlmJywgJ3JzdGF0aXgnLCAnc2pzdGF0cycsICdlbW1lYW5zJykKaW52aXNpYmxlKGxhcHBseShwYWNrYWdlcywgcmVxdWlyZSwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKSkKCnRoZW1lX3NldCh0aGVtZV9jb3dwbG90KGZvbnRfc2l6ZT0xMikpCnNvdXJjZSgnLi4vZGF0YVByb2Nlc3NpbmcuUicpIApzb3VyY2UoJy4uL3N0YXRpc3RpY2FsVGVzdHMuUicpCiNXcmFwcGVyIGZvciBicm0gbW9kZWxzIHN1Y2ggdGhhdCBpdCBzYXZlcyB0aGUgZnVsbCBtb2RlbCB0aGUgZmlyc3QgdGltZSBpdCBpcyBydW4sIG90aGVyd2lzZSBpdCBsb2FkcyBpdCBmcm9tIGRpc2sKcnVuX21vZGVsIDwtIGZ1bmN0aW9uKGV4cHIsIG1vZGVsTmFtZSwgcGF0aD0nLi4vYnJtc01vZGVscycsIHJldXNlID0gVFJVRSkgewogIHBhdGggPC0gcGFzdGUwKHBhdGgsJy8nLCBtb2RlbE5hbWUsICIuYnJtIikKICBpZiAocmV1c2UpIHsKICAgIGZpdCA8LSBzdXBwcmVzc1dhcm5pbmdzKHRyeShyZWFkUkRTKHBhdGgpLCBzaWxlbnQgPSBUUlVFKSkKICB9CiAgaWYgKGlzKGZpdCwgInRyeS1lcnJvciIpKSB7CiAgICBmaXQgPC0gZXZhbChleHByKQogICAgc2F2ZVJEUyhmaXQsIGZpbGUgPSBwYXRoKQogIH0KICBmaXQKfQpgYGAKCkZpcnN0LCBsZXQncyBsb2FkIHRoZSBkYXRhLiBUaGVzZSBkYXRhIGltcG9ydCBmdW5jdGlvbnMgYXJlIGRlZmluZWQgaW4gYGRhdGFQcm9jZXNzaW5nLlJgIHdoZXJlIEkgY29udmVydCB0aGUgcmF3IGRhdGEgaW50byBhIHVzdWFibGUgZGF0YWZyYW1lLiAKCmBgYHtyfQpkYXRhRGlyIDwtICcuLi9leHBlcmltZW50RGF0YS9mdWxsLmNzdicgIwpkZiA8LSBkYXRhSW1wb3J0KGRhdGFGaWxlID0gZGF0YURpciAsbm9ybWFsaXplPUYpICNUaGVzZSB0d28gZnVuY3Rpb25zIGFyZSBkZWZpbmVkIGluIGBkYXRhUHJvY2Vzc2luZy5SYAp0cmFqREYgPC0gaW1wb3J0VHJhakRhdGEoZGF0YUZpbGUgPSBkYXRhRGlyLG5vcm1hbGl6ZT1GKQojVHJpbSBsYXN0IHJvdW5kcwpkZjwtIHN1YnNldChkZiwgcm91bmQ8MTApICNMYXN0IHJvdW5kIGlzIHRoZSBib251cyByb3VuZCBhbmQgaXMgbm90IGluY2x1ZGVkIGluIHRoZSBiZWhhdmlvcmFsIGFuYWx5c2lzLCBzaW5jZSB0aGUganVkZ21lbnQgdGFzayBtYXkgYmlhcyBzdWJzZXF1ZW50IHBlcmZvcm1hbmNlCgpuX3JvdW5kcyA9IDkgI3dpdGhvdXQgYm9udXMgcm91bmQKbl90cmlhbHMgPSAyMCAjcGVyIHJvdW5kCmBgYAoKCiMjIERlbW9ncmFwaGljcwpgYGB7ciBlY2hvID0gRkFMU0V9CgojVG90YWwgcGFydGljaXBhbnRzCnBhc3RlMCgnUGFydGljaXBhbnRzOiAnLCBsZW5ndGgodW5pcXVlKGRmJGlkKSkpCgojQWdlCmFnZURGIDwtIGRkcGx5KGRmLCAuKGlkKSwgcGx5cjo6c3VtbWFyaXplLCAgYWdlPWFzLm51bWVyaWModW5pcXVlKGFnZSkpKQpwYXN0ZTAoJ0FnZTogJywgcHJldHR5TnVtKG1lYW4oYWdlREYkYWdlKSApLCAiIMKxICIgLCBwcmV0dHlOdW0oc2QoYWdlREYkYWdlKSkpCgojZ2VuZGVyCmdlbmRlckRGIDwtIGRkcGx5KGRmLCAuKGlkKSwgcGx5cjo6c3VtbWFyaXplLCAgbWFsZT11bmlxdWUoZ2VuZGVyKSkgIzEgaXMgbWFsZSwgMCBpcyBmZW1hbGUKZ2VuZGVyREYkbWFsZSA8LSBhcy5udW1lcmljKGxldmVscyhnZW5kZXJERiRtYWxlKVthcy5pbnRlZ2VyKGdlbmRlckRGJG1hbGUpXSkKcGFzdGUwKCJNYWxlczogIixzdW0oZ2VuZGVyREYkbWFsZSkpCgojdG90YWwgYm9udXMKYm9udXNEZiA8LSAgZGRwbHkoZGYsIC4oaWQpLCBwbHlyOjpzdW1tYXJpemUsICBib251cz1hcy5udW1lcmljKHVuaXF1ZSh0b3RhbEJvbnVzKSkpICNib251cwpwYXN0ZTAoIkVhcm5pbmdzIDoiLCBtZWFuKGJvbnVzRGYkYm9udXMpICArIDgsICIgVVNEIMKxICIsIHByZXR0eU51bShzZChib251c0RmJGJvbnVzKSkpICNpbmNsdWRpbmcgJDkgcGFydGljaXBhdGlvbiBmZWUKCiNkdXJhdGlvbgpkdXJhdGlvbkRGIDwtICBkZHBseShkZiwgLihpZCksIHBseXI6OnN1bW1hcml6ZSwgIGR1cmF0aW9uPWdyaWRfZHVyYXRpb25bMV0gKyBnYWJvcl9kdXJhdGlvblsxXSkgI2JvbnVzIHBsdXMgcGFydGljaXBhdGlvbiBmZWUKcGFzdGUwKCJUYXNrIER1cmF0aW9uOiAiLCBwcmV0dHlOdW0obWVhbihuYS5vbWl0KGR1cmF0aW9uREYkZHVyYXRpb24pKSksICAiIG1pbnMgwrEgIiwgcHJldHR5TnVtKHNkKG5hLm9taXQoZHVyYXRpb25ERiRkdXJhdGlvbikpKSkKCiMgdGltZSBiZXR3ZWVuIHRhc2tzCmdhcCA8LSBkZHBseShkZiwgLihpZCksIHBseXI6OnN1bW1hcml6ZSwgZ2FwID0gdW5pcXVlKGdyaWRfZ2Fib3JfZ2FwKSkKcGFzdGUwKCJHYXAgYmV0d2VlbiB0YXNrczogIiwgcHJldHR5TnVtKG1lYW4obmEub21pdChnYXAkZ2FwKSkpLCAiIGhvdXJzIMKxICIsIHByZXR0eU51bShzZChuYS5vbWl0KGdhcCRnYXApKSkpCgpgYGAKCgojIyBUcmFpbmluZyBQaGFzZQogCkJlZm9yZSB0aGUgbWFpbiBiYW5kaXQgdGFzaywgcGFydGljaXBhbnRzIHBlcmZvcm1lZCBhIHRyYWluaW5nIHBoYXNlIHdoZXJlIHRoZXkgd2VyZSByZXF1aXJlZCB0byBtYXRjaCBhIHRhcmdldCBzdGltdWxpIHVudGlsIGEgbGVhcm5pbmcgY3JpdGVyaW9uIHdhcyBtZXQgKGF0IGxlYXN0IDMyIHRyaWFscyBhbmQgYSBydW4gb2YgOSBvdXQgb2YgMTAgY29ycmVjdCkuIFRoZSB0YXNrIHVzZWQgdGhlIHNhbWUgc3RpbXVsaSBhbmQgaW5wdXRzIGFzIHRoZSBtYWluIGJhbmRpdCB0YXNrLCBhbmQgd2FzIHVzZWQgdG8gZmFtaWxpYXJpemUgcGFydGljaXBhbnRzIGFuZCBoYXZlIHRoZW0gYWNoaWV2ZSBhIHNpbWlsYXIgbGV2ZWwgb2YgZmx1ZW5jeSB3aXRoIGJvdGggc3BhdGlhbCBhbmQgY29uY2VwdHVhbCBkb21haW5zLiBMZXQncyBmaXJzdCBsb29rIGF0IHNvbWUgb2YgdGhlIHJlc3VsdHMuCgpQYXJ0aWNpcGFudHMgaGFkIGEgbG93ZXIgYWNjdXJhY3kgb24gdGhlIGNvbmNlcHR1YWwgdHJhaW5pbmcgKGByIGRhdCA8LSBkZHBseShkZiwgfmlkK2NvbnRleHQsIHBseXI6OnN1bW1hcml6ZSwgdHJhakNvcnJlY3QgPSBtZWFuKHRyYWpDb3JyZWN0KSwgdHJhakF2Z1N0ZXBzID0gbWVhbih0cmFqQXZnU3RlcHMpKSAKdHRlc3RQcmV0dHkoc3Vic2V0KGRhdCwgY29udGV4dCA9PSAnU3BhdGlhbCcpJHRyYWpDb3JyZWN0LCBzdWJzZXQoZGF0LCBjb250ZXh0ID09ICdDb25jZXB0dWFsJykkdHJhakNvcnJlY3QsIHBhaXJlZD1UKWApIGFuZCByZXF1aXJlZCBtb3JlIHRyaWFscyB0byByZWFjaCB0aGUgdHJhaW5pbmcgY3JpdGVyaW9uICgkWj0tNC4xJCwgJHA8LjAwMSQsICRyPS0uNDAkLCAkQkY+MTAwJCksIHdoaWNoIGlzIHRvIGJlIGV4cGVjdGVkIHNpbmNlIGl0IGlzIGludHVpdGl2ZWx5IG1vcmUgZGlmZmljdWx0LiAKCmBgYHtyfQojT3ZlcmFsbCBDb3JyZWN0IGNob2ljZXMKZGF0IDwtIGRkcGx5KGRmLCB+aWQrY29udGV4dCwgcGx5cjo6c3VtbWFyaXplLCB0cmFqQ29ycmVjdCA9IG1lYW4odHJhakNvcnJlY3QpLCB0cmFqQXZnU3RlcHMgPSBtZWFuKHRyYWpBdmdTdGVwcykpCnRyYWpwMWE8LSBnZ3Bsb3QoZGF0LCBhZXMoeCA9IGNvbnRleHQsIHkgPSB0cmFqQ29ycmVjdCwgY29sb3IgPSBjb250ZXh0KSkrCiAgZ2VvbV9saW5lKGFlcyhncm91cD1pZCksY29sb3IgPSAnYmxhY2snLCBhbHBoYSA9IDAuMSkrCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2hhcGUgPSBOQSwgZmlsbD1OQSwgY29sb3IgPSAnYmxhY2snLCB3aWR0aCA9IDAuMSkrCiAgZ2VvbV9xdWFzaXJhbmRvbShhbHBoYSA9IDAuNykrCiAgc3RhdF9zdW1tYXJ5KGZ1bi55PW1lYW4sIGdlb209J3BvaW50Jywgc2hhcGU9MjMsIGNvbG9yID0gJ2JsYWNrJywgc2l6ZSA9MykrCiAgeWxhYignUChjb3JyZWN0KScpKwogIHhsYWIoJycpKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIkRhcmsyIiwgbmFtZSA9ICIiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSdub25lJykKdHJhanAxYQoKI1RyaWFscyB1bnRpbCBjb21wbGV0ZQpkYXQgPC0gZGRwbHkodHJhakRGLCB+aWQrY29udGV4dCwgcGx5cjo6c3VtbWFyaXplLCB0cmFqVHJpYWxzID0gbWF4KHRyaWFsKSkKI3R0ZXN0UHJldHR5KHN1YnNldChkYXQsIGNvbnRleHQgPT0gJ1NwYXRpYWwnKSR0cmFqVHJpYWxzLCBzdWJzZXQoZGF0LCBjb250ZXh0ID09ICdDb25jZXB0dWFsJykkdHJhalRyaWFscywgcGFpcmVkPVQpICNEYXRhIGRvZXNuJ3QgbG9vayB2ZXJ5IG5vcm1hbAojcmFua3Rlc3RQcmV0dHkoc3Vic2V0KGRhdCwgY29udGV4dCA9PSAnU3BhdGlhbCcpJHRyYWpUcmlhbHMsIHN1YnNldChkYXQsIGNvbnRleHQgPT0gJ0NvbmNlcHR1YWwnKSR0cmFqVHJpYWxzLCBwYWlyZWQ9VCkgI0lzIHRoZXJlIGEgbWVhbmluZnVsIGRpZmZlcmVuY2UgaW4gdGhlIG51bWJlciBvZiB0cmlhbHMgbmVlZGVkIHRvIGZpbmlzaCB0aGUgdHJhaW5pbmcgcGhhc2U/ICNOb3RlIHNvbWV0aW1lcyBCYXllcyBGYWN0b3JzIGRpc3BsYXkgYXMgTkEgd2hlbiB0aGV5IGFyZSB2ZXJ5IGxhcmdlCgp0cmFqQ29tcGxldGUgPC0gZ2dwbG90KGRhdCwgYWVzKHggPSBjb250ZXh0LCB5ID0gdHJhalRyaWFscywgY29sb3IgPSBjb250ZXh0KSkrCiAgZ2VvbV9saW5lKGFlcyhncm91cD1pZCksY29sb3IgPSAnYmxhY2snLCBhbHBoYSA9IDAuMSkrCiAgZ2VvbV9xdWFzaXJhbmRvbSggYWxwaGEgPSAwLjYpKwogIGdlb21fYm94cGxvdChjb2xvcj0nYmxhY2snLCBmaWxsPSBOQSwgd2lkdGggPS4yLCBvdXRsaWVyLnNoYXBlID0gTkEpKwogIHN0YXRfc3VtbWFyeShmdW4ueSA9IG1lYW4sIGdlb209J3BvaW50Jywgc2hhcGUgPSAyMyxzaXplPTMsIGNvbG9yID0gJ2JsYWNrJykrCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMzIsIGxpbmV0eXBlID0gJ2Rhc2hlZCcpKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIkRhcmsyIiwgbmFtZSA9ICIiKSArCiAgeWxhYignVHJpYWxzIFVudGlsIENvbXBsZXRlJykrCiAgeGxhYignJykrCiAgI2Nvb3JkX2NhcnRlc2lhbih5bGltPWMoMzAsMTI4KSwgKSsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzPWMoMzIsNjQsIDk2LCAxMjgpLCBsaW1pdHMgPSBjKDMyLDEyOCkpKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICdub25lJykKdHJhakNvbXBsZXRlCgpgYGAKCldlIGNhbiBhbHNvIGxvb2sgYXQgdGhlIG1hZ25pdHVkZSBvZiBlcnJvcnMgdnMuIHRoZSBmcmVxdWVudnkgb2Ygb2NjdXJlbmNlLCB3aGljaCBnaXZlcyB1cyBhIG5pY2UgU2hlcGFyZCAoMTk4Nykgc3R5bGUgZ2VuZXJhbGl6YXRpb24gZ3JhZGllbnQuCmBgYHtyfQojTWFnbml0dWRlIG9mIGVycm9yIHZzLiBmcmVxdWVuY3kKZ3JhZGllbnRERiA8LSBkZHBseSh0cmFqREYsIH5jb250ZXh0K21hbmhhdHRhbkVycm9yLHBseXI6OnN1bW1hcml6ZSwgY291bnRzID0gdGFibGUobWFuaGF0dGFuRXJyb3IpKSAKI05vcm1hbGl6ZSBpbnRvIGEgcGVyY2VudGFnZQpncmFkaWVudERGW2dyYWRpZW50REYkY29udGV4dCA9PSAnQ29uY2VwdHVhbCcsJ1AnXSA8LSBncmFkaWVudERGW2dyYWRpZW50REYkY29udGV4dCA9PSAnQ29uY2VwdHVhbCcsJ2NvdW50cyddL3N1bShncmFkaWVudERGW2dyYWRpZW50REYkY29udGV4dCA9PSAnQ29uY2VwdHVhbCcsJ2NvdW50cyddKQpncmFkaWVudERGW2dyYWRpZW50REYkY29udGV4dCA9PSAnU3BhdGlhbCcsJ1AnXSA8LSBncmFkaWVudERGW2dyYWRpZW50REYkY29udGV4dCA9PSAnU3BhdGlhbCcsJ2NvdW50cyddL3N1bShncmFkaWVudERGW2dyYWRpZW50REYkY29udGV4dCA9PSAnU3BhdGlhbCcsJ2NvdW50cyddKQoKcEVycm9yPC0gZ2dwbG90KGdyYWRpZW50REYsIGFlcyh4ID0gbWFuaGF0dGFuRXJyb3IsIHkgPSBQLCBjb2xvciA9IGNvbnRleHQsIHNoYXBlID0gY29udGV4dCkpKwogIGdlb21fbGluZSgpKwogIGdlb21fcG9pbnQoKSsKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbT1jKDAsNSkpKwogIHlsYWIoJ1AoZXJyb3IpJykrCiAgeGxhYignTWFnbml0dWRlIG9mIEVycm9yIChNYW5oYXR0YW4gZGlzdGFuY2UpJykrCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiLCBuYW1lID0gIlRhc2siKSsKICBzY2FsZV9zaGFwZV9tYW51YWwoIHZhbHVlcyA9IGMoMTYsMTUpLG5hbWUgPSAiVGFzayIpKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj1jKDEsMSksIGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygxLDEpKQoKcEVycm9yCmBgYAoKSG93IGRpZCBhY2N1cmFjeSBkaWZmZXIgZm9yIHRoZSBkaWZmZXJlbnQgb3B0aW9ucz8KYGBge3J9CgpzcGF0aWFsQ291bnRzIDwtIGRkcGx5KHN1YnNldCh0cmFqREYsIGNvbnRleHQgPT0gJ1NwYXRpYWwnKSwgLih4LCB5KSwgcGx5cjo6c3VtbWFyaXplLCBjb3JyZWN0ID0gc3VtKHRyYWpDb3JyZWN0KS9sZW5ndGgodHJhakNvcnJlY3QpKQpuYW1lcyhzcGF0aWFsQ291bnRzKSA8LSBjKCJYIiwgIlkiLCAiQWNjdXJhY3kiKQpzcGF0aWFsQ291bnRzJHRhc2sgPC0gJ1NwYXRpYWwnCgpjb25jZXB0Q291bnRzIDwtIGRkcGx5KHN1YnNldChkZiwgY29udGV4dCA9PSAnQ29uY2VwdHVhbCcpLCAuKHgsIHkpLCBwbHlyOjpzdW1tYXJpemUsIGNvcnJlY3QgPSBzdW0odHJhakNvcnJlY3QpL2xlbmd0aCh0cmFqQ29ycmVjdCkpCm5hbWVzKGNvbmNlcHRDb3VudHMpIDwtIGMoIlgiLCAiWSIsICJBY2N1cmFjeSIpCmNvbmNlcHRDb3VudHMkdGFzayA8LSAnQ29uY2VwdHVhbCcKCnRyYWluaW5nQWNjdXJhY3lERiA8LXJiaW5kKHNwYXRpYWxDb3VudHMsIGNvbmNlcHRDb3VudHMpCnRyYWpoZWF0bWFwPC0gZ2dwbG90KHRyYWluaW5nQWNjdXJhY3lERiwgYWVzKHg9WCwgeSA9IFksIGZpbGw9QWNjdXJhY3kpKSArCiAgZ2VvbV90aWxlKCkrCiAgc2NhbGVfZmlsbF9kaXN0aWxsZXIocGFsZXR0ZSA9ICJTcGVjdHJhbCIsIG5hbWUgPSAnUChjb3JyZWN0KScsbGltaXRzID0gYygwLDEpLGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkrCiAgdGhlbWVfY2xhc3NpYygpICsKICBmYWNldF9ncmlkKH50YXNrKSsKICBjb29yZF9lcXVhbCgpICsKICB0aGVtZShzdHJpcC5iYWNrZ3JvdW5kPWVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLmtleT1lbGVtZW50X3JlY3QoY29sb3I9TkEpLCBheGlzLmxpbmU9ZWxlbWVudF9ibGFuaygpLGF4aXMudGV4dC54PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksYXhpcy50aWNrcz1lbGVtZW50X2JsYW5rKCksIHBhbmVsLmJhY2tncm91bmQ9ZWxlbWVudF9ibGFuaygpLHBhbmVsLmJvcmRlcj1lbGVtZW50X2JsYW5rKCkscGFuZWwuZ3JpZC5tYWpvcj1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vcj1lbGVtZW50X2JsYW5rKCkscGxvdC5iYWNrZ3JvdW5kPWVsZW1lbnRfYmxhbmsoKSkrCiAgbGFicyh4ID0gJycsIHkgPSAnJykKdHJhamhlYXRtYXAKYGBgCgojIyBQZXJmb3JtYW5jZQoKTm93IGxldCdzIGZpbmFsbHkgbG9vayBhdCBwZXJmb3JtYW5jZSBvbiB0aGUgYmFuZGl0IHRhc2suCgpgYGB7cn0KI0NvbnN0cnVjdCBwbG90dGluZyBkYXRhZnJhbWVzCm1lYW5ERiA8LSBkZHBseShkZiwgLihpZCwgY29udGV4dCwgZW52aXJvbm1lbnQsIGNvbnRleHRPcmRlciksIHBseXI6OnN1bW1hcml6ZSwgbWVhblNjb3JlID0gbWVhbih6KSkKY29uY2VwdHVhbFNjb3JlcyA8LSBzdWJzZXQobWVhbkRGLCBjb250ZXh0ID09ICJDb25jZXB0dWFsIikKc3BhdGlhbFNjb3JlcyA8LSBzdWJzZXQobWVhbkRGLCBjb250ZXh0ID09ICJTcGF0aWFsIikKbWVyZ2VkREYgPC0gbWVyZ2UoY29uY2VwdHVhbFNjb3Jlcywgc3BhdGlhbFNjb3JlcywgYnkgPSJpZCIpCmpvaW5lZERGIDwtIHJiaW5kKGNvbmNlcHR1YWxTY29yZXMsIHNwYXRpYWxTY29yZXMpCmJvdGhUYXNrc0RGIDwtIGRkcGx5KGpvaW5lZERGLCAuKGlkLCBlbnZpcm9ubWVudCwgY29udGV4dE9yZGVyKSwgcGx5cjo6c3VtbWFyaXplLCBtZWFuU2NvcmUgPSBtZWFuKG1lYW5TY29yZSkpCnJhbmRvbURGIDwtIHJlYWQuY3N2KCIuLi9yYXRpb25hbE1vZGVscy9yYW5kb20uY3N2IikgI2xvYWQgcmFuZG9tIG1vZGVsCgpqb2luZWRERiRjb250ZXh0T3JkZXIgPC0gZmFjdG9yKGpvaW5lZERGJGNvbnRleHRPcmRlcikKbGV2ZWxzKGpvaW5lZERGJGNvbnRleHRPcmRlcik8LSBjKCJTcGF0aWFsIEZpcnN0IiwgIkNvbmNlcHR1YWwgRmlyc3QiKQoKYGBgCk92ZXJhbGwsIHBhcnRpY2lwYW50cyBwZXJmb3JtZWQgZmFyIGJldHRlciB0aGFuIGNoYW5jZSBpbiBib3RoIENvbmNlcHR1YWwgKCR0KDEyOCk9MjQuNiQsICRwPC4wMDEkLCAkZD0yLjIkLCAkQkY+MTAwJCkgYW5kIFNwYXRpYWwgdGFza3MgKCR0KDEyOCk9MzQuNiQsICRwPC4wMDEkLCAkZD0zLjAkLCAkQkY+MTAwJCkuICBMZXQncyBub3cgZG8gYSB0d28gd2F5IG1peGVkIEFOT1ZBIHRvIHNlZSBob3cgb3VyIGNvbnRleHQgeCBlbnZpcm9ubWVudCBkZXNpZ24gaW5mbHVlbmNlZCBwZXJmb3JtYW5jZS4KCmBgYHtyfQojVHdvIHdheSBtaXhlZCBBTk9WQTogY29udGV4dCBpcyB3aXRoaW4sIGVudmlyb25tZW50IGlzIGJldHdlZW4gCmRkPC1kZHBseShyYmluZChjb25jZXB0dWFsU2NvcmVzLCBzcGF0aWFsU2NvcmVzKSwgfmlkK2NvbnRleHQrZW52aXJvbm1lbnQsIHN1bW1hcmlzZSwgbT1tZWFuKG1lYW5TY29yZSkpCmRkJGlkIDwtIGZhY3RvcihkZCRpZCkKcmVzLmFvdiA8LSBhb3YobSB+IGVudmlyb25tZW50KmNvbnRleHQgKyBFcnJvcihpZC9jb250ZXh0KSwgZGF0YT1kZCkKYW5vdmFfc3RhdHMocmVzLmFvdikKIyBOb3cgbGV0J3MgcmVwbGljYXRlIHZpYSBSb2J1c3QgQU5PVkEKYnd0cmltKG0gfiBlbnZpcm9ubWVudCpjb250ZXh0LCBpZCA9IGlkLCBkYXRhPWRkLCB0ciA9IDAuMikgI3VzaW5nIDIwJSB0cmltbWVkIG1lYW5zCnNwcGJhKG0gfiBlbnZpcm9ubWVudCpjb250ZXh0LCBpZCA9IGlkLCBkYXRhPWRkKSAjTWFpbiBmaXhlZCBlZmZlY3QKc3BwYmIobSB+IGVudmlyb25tZW50KmNvbnRleHQsIGlkID0gaWQsIGRhdGE9ZGQpICNXaXRoaW4tc3ViZWN0IGVmZmVjdAojTm93IGNvbXB1dGUgQmF5ZXMgZmFjdG9yCmludmlzaWJsZShiZiA8LSBhbm92YUJGKG0gfiBlbnZpcm9ubWVudCpjb250ZXh0K2lkLCAgZGF0YT1kZCwgIHdoaWNoUmFuZG9tPSJpZCIpKQpiZgoKYGBgCkxvb2tzIGxpa2Ugc3Ryb25nIGV2aWRlbmNlIGZvciBkaWZmZXJlbmNlcy4KCmBgYHtyfQojTWVhbiBwZXJmb3JtYW5jZSBwbG90cwpwMWEgPC0gZ2dwbG90KGpvaW5lZERGLCBhZXMoeCA9IGludGVyYWN0aW9uKGNvbnRleHQsIGVudmlyb25tZW50KSwgeSA9IG1lYW5TY29yZSwgY29sb3IgPSBjb250ZXh0KSkrCiAgZ2VvbV9ib3hwbG90KGZpbGw9TkEsIGNvbG9yID0gJ2JsYWNrJywgb3V0bGllci5zaGFwZT1OQSwgd2lkdGggPSAwLjIpKwogIGdlb21fbGluZShhZXMoZ3JvdXA9aWQpLCBjb2xvciA9ICdibGFjaycsIGFscGhhID0gMC4xKSsKICBnZW9tX3F1YXNpcmFuZG9tKGFscGhhID0gMC43KSsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBtZWFuKHJhbmRvbURGJG1lYW5SZXdhcmQpLCBjb2xvciA9ICdibGFjaycsIGxpbmV0eXBlID0gJ2Rhc2hlZCcpKwogIHN0YXRfc3VtbWFyeShmdW4ueSA9IG1lYW4sIHNoYXBlID0gMjMsIGdlb209J3BvaW50Jywgc2l6ZSA9IDMsIGZpbGwgPSBOQSwgY29sb3IgPSdibGFjaycpKwogICNmYWNldF9ncmlkKH5lbnZpcm9ubWVudCkrCiAgeWxhYigiTWVhbiBSZXdhcmQgXHUwMEIxU0UiKSsKICB4bGFiKCcnKSsKICBhbm5vdGF0ZSgndGV4dCcsIHggPSAxLjUsIHkgPSAxMTAsIGxhYmVsPSdSb3VnaCcpKwogIGFubm90YXRlKCd0ZXh0JywgeCA9IDMuNSwgeSA9IDExMCwgbGFiZWw9J1Ntb290aCcpKwogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzPWMoIkNvbmNlcHR1YWwiLCAiU3BhdGlhbCIsICJDb25jZXB0dWFsIiwgIlNwYXRpYWwiKSkrCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiLCBuYW1lID0gIiIpICsKICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIkRhcmsyIiwgbmFtZSA9ICIiKSArCiAgZ2VvbV9zaWduaWYoeV9wb3NpdGlvbiA9IGMoOTUsIDk3LCAxMDMpLCAgeG1pbiA9IGMoMSwzLCAxLjUpLCB4bWF4ID0gYygyLDQsIDMuNSksIGFubm90YXRpb24gPSBjKCJCRj4xMDAiLCJCRiA9IDE0IiwgIkJGID0gMTIiKSwgY29sb3IgPSAnYmxhY2snKSsKICAjZ2VvbV9zaWduaWYoY29tcGFyaXNvbnM9bGlzdCggYygiQ29uY2VwdHVhbCIsICJTcGF0aWFsIiksIGMoIkNvbmNlcHR1YWwiLCAiU3BhdGlhbCIpKSwgYW5ub3RhdGlvbnM9YygiIiwiIiksIGNvbD0iYmxhY2siKSsgIyAKICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTIsICBmYW1pbHk9InNhbnMiKSxzdHJpcC5iYWNrZ3JvdW5kPWVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLmtleT1lbGVtZW50X3JlY3QoY29sb3I9TkEpLCBsZWdlbmQucG9zaXRpb249J05vbmUnKQpwMWEKYGBgCgpQYXJ0aWNpcGFudHMgZWFybmVkIGhpZ2hlciByZXdhcmRzIGluIHRoZSBTcGF0aWFsIHRoYW4gdGhlIENvbmNlcHR1YWwgdGFzayAob25lIHNhbXBsZSAkdCQtdGVzdDogJHQoMTI4KT0tNi4wJCwgJHA8LjAwMSQsICRkPTAuNSQsICRCRj4xMDAkKSBhbmQgYmV0dGVyIGluIHNtb290aCB0aGFuIGluIHJvdWdoIGVudmlyb25tZW50cyAodHdvIHNhbXBsZSAkdCQtdGVzdDogJHQoMTI3KT0zLjEkLCAkcD0uMDAzJCwgJGQ9MC41JCwgJEJGPTEyJCkuIFdlIGFsc28gZmluZCBjb3JyZWxhdGVkIHBlcmZvcm1hbmNlIGJldHdlZW4gdGFza3MgKCRyPS41MyQsICRwPC4wMDEkLCAkQkY+MTAwJCkuCgpgYGB7ciAgZXZhbD1GLCBlY2hvPVR9CiNzdGF0aXN0aWNhbCB0ZXN0cwp0dGVzdFByZXR0eShjb25jZXB0dWFsU2NvcmVzJG1lYW5TY29yZSwgbXU9bWVhbihyYW5kb21ERiRtZWFuUmV3YXJkKSkgI2NvbXBhcmVkIHRvIGNoYW5jZQp0dGVzdFByZXR0eShzcGF0aWFsU2NvcmVzJG1lYW5TY29yZSwgbXU9bWVhbihyYW5kb21ERiRtZWFuUmV3YXJkKSkKCiNULXRlc3RzCnR0ZXN0UHJldHR5KGNvbmNlcHR1YWxTY29yZXMkbWVhblNjb3JlLCBzcGF0aWFsU2NvcmVzJG1lYW5TY29yZSwgdmFyLmVxdWFsID0gVFJVRSwgcGFpcmVkPVQpICNjb250ZXh0CnR0ZXN0UHJldHR5KHN1YnNldChib3RoVGFza3NERiwgZW52aXJvbm1lbnQ9PSJTbW9vdGgiKSRtZWFuU2NvcmUsIHN1YnNldChib3RoVGFza3NERiwgZW52aXJvbm1lbnQ9PSJSb3VnaCIpJG1lYW5TY29yZSwgdmFyLmVxdWFsID0gVFJVRSkgI2Vudmlyb25tZW50CmNvclRlc3RQcmV0dHkoY29uY2VwdHVhbFNjb3JlcyRtZWFuU2NvcmUsIHNwYXRpYWxTY29yZXMkbWVhblNjb3JlKSAjY29ycmVsYXRlZCBwZXJmb3JtYW5jZQp0dGVzdFByZXR0eShzdWJzZXQoY29uY2VwdHVhbFNjb3JlcywgZW52aXJvbm1lbnQ9PSdTbW9vdGgnKSRtZWFuU2NvcmUsIHN1YnNldChzcGF0aWFsU2NvcmVzLCBlbnZpcm9ubWVudD09IlNtb290aCIpJG1lYW5TY29yZSwgdmFyLmVxdWFsID0gVFJVRSwgcGFpcmVkPVQpICNjb250ZXh0CnR0ZXN0UHJldHR5KHN1YnNldChjb25jZXB0dWFsU2NvcmVzLCBlbnZpcm9ubWVudD09J1JvdWdoJykkbWVhblNjb3JlLCBzdWJzZXQoc3BhdGlhbFNjb3JlcywgZW52aXJvbm1lbnQ9PSJSb3VnaCIpJG1lYW5TY29yZSwgdmFyLmVxdWFsID0gVFJVRSwgcGFpcmVkPVQsIG1heEJGID0gSW5mKSAjY29udGV4dAoKYGBgCkNvcnJlbGF0aW9uIGJldHdlZW4gdGFza3M6CgpgYGB7cn0KI2NvclRlc3RQcmV0dHkoY29uY2VwdHVhbFNjb3JlcyRtZWFuU2NvcmUsIHNwYXRpYWxTY29yZXMkbWVhblNjb3JlKQpwMWIgPC0gZ2dwbG90KG1lcmdlZERGLCBhZXMoeD1tZWFuU2NvcmUueCwgeSA9IG1lYW5TY29yZS55LCBjb2xvciA9IGVudmlyb25tZW50LngsIHNoYXBlPSBlbnZpcm9ubWVudC54KSkgKwogIGdlb21fYWJsaW5lKHNsb3BlPTEsIGludGVyY2VwdD0wLCBsaW5ldHlwZT0nZGFzaGVkJykgKwogIGdlb21fcG9pbnQoYWxwaGE9MC45LCBzaXplID0gMi41KSsKICB5bGFiKCdTcGF0aWFsIFJld2FyZCcpKwogIHhsYWIoJ0NvbmNlcHR1YWwgUmV3YXJkJykrCiAgeGxpbSg0MCwxMDApKwogIHlsaW0oNDAsMTAwKSArCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gNTAsIHkgPSA5NSwgbGFiZWwgPSAiJ3IgPSAuNTMnIConLCcqIH5+J0JGID4gMTAwJyIsIHBhcnNlPVRSVUUsIHNpemU9NSwgZmFtaWx5PSJzYW5zIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj1jKDEsMCksbGVnZW5kLmp1c3RpZmljYXRpb249YygxLDApLCBzdHJpcC5iYWNrZ3JvdW5kPWVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLmtleT1lbGVtZW50X3JlY3QoY29sb3I9TkEpLCB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTIsICBmYW1pbHk9InNhbnMiKSkrCiAgI3NjYWxlX2NvbG9yX3JpY2thbmRtb3J0eShuYW1lPSJFbnZpcm9ubWVudCIsIHBhbGV0dGUgPSAic2Nod2lmdHkiKSsKICBzY2FsZV9jb2xvcl9tYW51YWwobmFtZT0iRW52aXJvbm1lbnQiLCB2YWx1ZXM9YygiIzI0MzI1RkZGIiwgJyNCN0U0RjlGRicpKSsKICBzY2FsZV9zaGFwZV9tYW51YWwobmFtZT0iRW52aXJvbm1lbnQiLCB2YWx1ZXM9IGMoMTcsMTYpKQpwMWIKYGBgCgojIyMgT3JkZXIgZWZmZWN0CgpXZSBmaW5kIGFuIGludGVyZXN0aW5nIG9uZS1kaXJlY3Rpb25hbCBvcmRlciBlZmZlY3QuIFBhcnRpY2lwYW50cyBwZXJmb3JtZWQgYmV0dGVyIG9uIHRoZSBjb25jZXB0dWFsIHRhc2sgb25jZSB0aGV5IGhhZCBleHBlcmllbmNlIHdpdGggdGhlIHNwYXRpYWwgdGFzayAoYHIgdHRlc3RQcmV0dHkoc3Vic2V0KGNvbmNlcHR1YWxTY29yZXMsIGNvbnRleHRPcmRlcj09MCkkbWVhblNjb3JlLCBzdWJzZXQoY29uY2VwdHVhbFNjb3JlcywgY29udGV4dE9yZGVyPT0xKSRtZWFuU2NvcmUsIHZhci5lcXVhbCA9IFRSVUUpYC4gVGhpcyB3YXMgbm90IHRoZSBjYXNlIGZvciB0aGUgc3BhdGlhbCB0YXNrLCB3aGVyZSBwZXJmb3JtYW5jZSBkaWQgbm90IGRpZmZlciBpZiBwZXJmb3JtZWQgZmlyc3Qgb3Igc2Vjb25kIChgciB0dGVzdFByZXR0eShzdWJzZXQoc3BhdGlhbFNjb3JlcywgY29udGV4dE9yZGVyPT0wKSRtZWFuU2NvcmUsIHN1YnNldChzcGF0aWFsU2NvcmVzLCBjb250ZXh0T3JkZXI9PTEpJG1lYW5TY29yZSwgdmFyLmVxdWFsID0gVFJVRSlgKS4gIFRodXMsIGV4cGVyaWVuY2Ugd2l0aCBzcGF0aWFsIHNlYXJjaCBib29zdGVkIHBlcmZvcm1hbmNlIG9uIGNvbmNlcHR1YWwgc2VhcmNoLCBidXQgbm90IHZpY2UgdmVyc2EuCgpgYGB7cn0KZGYkRmlyc3RUYXNrIDwtIGlmZWxzZShkZiRjb250ZXh0T3JkZXI9PTAsICdTcGF0aWFsIEZpcnN0JywgJ0NvbmNlcHR1YWwgRmlyc3QnKSAjd2hpY2ggdGFzayB3YXMgcGVyZm9ybWVkIGZpcnN0PwpkZiR0YXNrT3JkZXIgPC0gaWZlbHNlKChkZiRGaXJzdFRhc2s9PSJTcGF0aWFsIEZpcnN0IiAmIGRmJGNvbnRleHQgPT0gIlNwYXRpYWwiKSB8KGRmJEZpcnN0VGFzaz09IkNvbmNlcHR1YWwgRmlyc3QiICYgZGYkY29udGV4dCA9PSAiQ29uY2VwdHVhbCIpLCAxLCAyICkgCmRmJEZpcnN0VGFzayA8LSBmYWN0b3IoZGYkRmlyc3RUYXNrLCBsZXZlbHMgPSBjKCJDb25jZXB0dWFsIEZpcnN0IiwiU3BhdGlhbCBGaXJzdCIpKQpvcmRlckRGIDwtIGRkcGx5KGRmLCAuKGlkLCBjb250ZXh0LCBlbnZpcm9ubWVudCwgRmlyc3RUYXNrLCB0YXNrT3JkZXIpLCBwbHlyOjpzdW1tYXJpemUsIG1lYW5TY29yZSA9IG1lYW4oeikpCgpwT3JkZXIgPC0gZ2dwbG90KG9yZGVyREYsIGFlcyh4ID0gaW50ZXJhY3Rpb24oY29udGV4dCxGaXJzdFRhc2spLCB5ID0gbWVhblNjb3JlLCBmaWxsID0gY29udGV4dCwgY29sb3IgPSBjb250ZXh0KSkrCiAgZ2VvbV9ib3hwbG90KCBjb2xvciA9ICdibGFjaycsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAxKSwgb3V0bGllci5zaGFwZT1OQSwgd2lkdGggPSAwLjIsIGFscGhhID0wKSsKICBnZW9tX3F1YXNpcmFuZG9tKGFscGhhID0gMC43LCBkb2RnZS53aWR0aCA9IDEpKwogICNnZW9tX2xpbmUoYWVzKGdyb3VwPWlkKSwgY29sb3IgPSAnYmxhY2snLCBhbHBoYSA9IDAuMSkrCiAgc3RhdF9zdW1tYXJ5KGZ1bi55ID0gbWVhbiwgc2hhcGUgPSAyMywgZ2VvbT0ncG9pbnQnLCBzaXplID0gMywgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDEpLCBjb2xvciA9J2JsYWNrJywgZmlsbCA9IE5BKSsKICAjc3RhdF9zdW1tYXJ5KGZ1bi55PW1lYW4sIGdlb209J2JhcicsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAxKSwgY29sb3I9J2JsYWNrJykrCiAgI3N0YXRfc3VtbWFyeShmdW4uZGF0YSA9IG1lYW5fY2xfYm9vdCwgZ2VvbT0nZXJyb3JiYXInLCBjb2xvcj0nYmxhY2snLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMSksIHdpZHRoID0gLjIpKwogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAnRGFyazInLCBuYW1lPSAnVGFzaycpKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gJ0RhcmsyJywgbmFtZT0gJ1Rhc2snKSsKICBhbm5vdGF0ZSgndGV4dCcsIHggPSAxLjUsIHkgPSAxMTgsIGxhYmVsPSdDb25jZXB0dWFsIEZpcnN0JykrCiAgYW5ub3RhdGUoJ3RleHQnLCB4ID0gMy41LCB5ID0gMTE4LCBsYWJlbD0nU3BhdGlhbCBGaXJzdCcpKwogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzPWMoIkNvbmNlcHR1YWwiLCAiU3BhdGlhbCIsICJDb25jZXB0dWFsIiwgIlNwYXRpYWwiKSkrCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gbWVhbihyYW5kb21ERiRtZWFuUmV3YXJkKSwgY29sb3IgPSAnYmxhY2snLCBsaW5ldHlwZSA9ICdkYXNoZWQnKSsKICAjY29vcmRfY2FydGVzaWFuKHlsaW0gPWMoNDAsMTIwKSkrCiAgeGxhYignJykrCiAgeWxhYignTWVhbiBSZXdhcmQgwrFTRScpKwogIGdlb21fc2lnbmlmKHlfcG9zaXRpb24gPSBjKDEwMCwgMTA4KSwgIHhtaW4gPSBjKDEsMiksIHhtYXggPSBjKDMsNCksIGFubm90YXRpb24gPSBjKCJCRj02LjQiLCJCRj0wLjY3IiksIGNvbG9yID0gJ2JsYWNrJykrCiAgI3RoZW1lKGxlZ2VuZC5wb3NpdGlvbj1jKDAuMDUsMSksIGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygwLDEpLCBsZWdlbmQuZGlyZWN0aW9uPSdob3Jpem9udGFsJykKICB0aGVtZShsZWdlbmQucG9zaXRpb249J25vbmUnKQpwT3JkZXIKYGBgCgoKIyMgTGVhcm5pbmcgb3ZlciB0cmlhbHMgYW5kIHJvdW5kcwpQYXJ0aWNpcGFudHMgaW1wcm92ZWQgc3Ryb25nbHkgb3ZlciB0cmlhbHMgKFBlYXJzb24gY29ycmVsYXRpb24gYmV0d2VlbiBzY29yZSBhbmQgdHJpYWwgbnVtYmVyOiBgciB0ZGYgPC0gZGRwbHkoZGYsIC4odHJpYWwpLCBwbHlyOjpzdW1tYXJpemUsIG1lYW5TY29yZT1tZWFuKHopKQpjb3JUZXN0UHJldHR5KHRkZiRtZWFuU2NvcmUsIHRkZiR0cmlhbCkgYCkgYW5kIHRvIGEgbGVzc2VyIGV4dGVudCBvdmVyIHJvdW5kcyAoYHIgcmRmIDwtIGRkcGx5KGRmLCAuKHJvdW5kKSwgcGx5cjo6c3VtbWFyaXplLCBtZWFuU2NvcmU9bWVhbih6KSkKY29yVGVzdFByZXR0eShyZGYkbWVhblNjb3JlLCByZGYkcm91bmQpYCkuCmBgYHtyfQojTWVhbiBzY29yZSBvdmVyIHRyaWFsCnRyaWFsREYgPC0gZGRwbHkoZGYsIC4oaWQsIGNvbnRleHQsIGVudmlyb25tZW50LCB0cmlhbCksIHBseXI6OnN1bW1hcml6ZSwgbWVhblNjb3JlPW1lYW4oeikpCnJhbmRvbURGIDwtIHJlYWQuY3N2KCIuLi9yYXRpb25hbE1vZGVscy9yYW5kb20uY3N2IikgI2xvYWQgcmFuZG9tIG1vZGVsCgpwM2EgPC0gZ2dwbG90KHRyaWFsREYsIGFlcyh4PXRyaWFsLCB5ID0gbWVhblNjb3JlLCBjb2xvciA9IGNvbnRleHQpKSArCiAgc3RhdF9zdW1tYXJ5KGZ1bi55ID0gbWVhbiwgZ2VvbSA9ICdsaW5lJykrCiAgc3RhdF9zdW1tYXJ5KGZ1bi5kYXRhID0gbWVhbl9zZSxhZXMgKCBmaWxsPWNvbnRleHQpLCBnZW9tID0gJ3JpYmJvbicsIGFscGhhID0gMC43LCBjb2xvcj1OQSkgKwogIHN0YXRfc3VtbWFyeShkYXRhID0gcmFuZG9tREYsIGFlcyh4PXRyaWFsLCB5ID0gbWVhblJld2FyZCksIGZ1bi55ID0gbWVhbiwgZ2VvbT0nbGluZScsIGNvbG9yID0gJ2JsYWNrJywgZmlsbD1OQSwgbGluZXR5cGUgPSAnZGFzaGVkJykrCiAgI2dlb21faGxpbmUoeWludGVyY2VwdCA9ICA1MCwgbGluZXR5cGUgPSAnZGFzaGVkJywgY29sb3IgPSAnYmxhY2snKSsKICBmYWNldF9ncmlkKH5lbnZpcm9ubWVudCkrCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJEYXJrMiIsIG5hbWU9IlRhc2siICkgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIkRhcmsyIiwgbmFtZT0iVGFzayIpICsKICAjY29vcmRfY2FydGVzaWFuKHlsaW09Yyg0OSw5NSkpKwogIHlsYWIoIk1lYW4gUmV3YXJkIFx1MDBCMVNFIikgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gcm91bmQoc2VxKDAsMjAsIGJ5ID0gNSksMSkpKwogIHhsYWIoIlRyaWFsIikrCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPWMoMSwgMC4xNSksIGxlZ2VuZC5qdXN0aWZpY2F0aW9uPWMoMSwwKSwgc3RyaXAuYmFja2dyb3VuZD1lbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5rZXk9ZWxlbWVudF9ibGFuaygpLCBsZWdlbmQuYmFja2dyb3VuZD1lbGVtZW50X2JsYW5rKCkpCnAzYQoKI01lYW4gc2NvcmUgb3ZlciByb3VuZApyb3VuZERGIDwtIGRkcGx5KGRmLCAuKGlkLCBjb250ZXh0LCBlbnZpcm9ubWVudCwgcm91bmQpLCBwbHlyOjpzdW1tYXJpemUsIG1lYW5TY29yZT1tZWFuKHopKQoKcFJvdW5kIDwtIGdncGxvdChyb3VuZERGLCBhZXMoeD1yb3VuZCwgeSA9IG1lYW5TY29yZSwgY29sb3IgPSBjb250ZXh0ICkpICsKICBzdGF0X3N1bW1hcnkoZnVuLnkgPSBtZWFuLCBnZW9tID0gJ2xpbmUnKSsKICBzdGF0X3N1bW1hcnkoZnVuLmRhdGEgPSBtZWFuX3NlLGFlcyhmaWxsPWNvbnRleHQpLCBnZW9tID0gJ3JpYmJvbicsIGFscGhhID0gMC43LCBjb2xvcj1OQSkgKwogIHN0YXRfc3VtbWFyeShkYXRhID0gcmFuZG9tREYsIGFlcyh4PXRyaWFsLCB5ID0gbWVhblJld2FyZCksIGZ1bi55ID0gbWVhbiwgZ2VvbT0nbGluZScsIGNvbG9yID0gJ2JsYWNrJywgZmlsbD1OQSwgbGluZXR5cGUgPSAnZGFzaGVkJykrCiAgY29vcmRfY2FydGVzaWFuKHhsaW09YygwLDkpKSsKICBmYWNldF9ncmlkKH5lbnZpcm9ubWVudCkrCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJEYXJrMiIsIG5hbWU9IlRhc2siKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiLCBuYW1lPSJUYXNrIikgKwogIHlsYWIoIk1lYW4gUmV3YXJkIFx1MDBCMVNFIikgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gcm91bmQoc2VxKDAsOSwgYnkgPSAyKSwxKSkrCiAgI2Nvb3JkX2NhcnRlc2lhbih5bGltPWMoMjAsNTApKSsKICB4bGFiKCJSb3VuZCIpKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj1jKDAuMDUsIDAuMSksIGxlZ2VuZC5qdXN0aWZpY2F0aW9uPWMoMCwwKSwgc3RyaXAuYmFja2dyb3VuZD1lbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5iYWNrZ3JvdW5kPWVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLmtleT1lbGVtZW50X3JlY3QoY29sb3I9TkEpKQoKcFJvdW5kCmBgYAoKIyMgUGF0dGVybnMgb2YgU2VhcmNoCiMjIyBMb2NhbGl0eSBvZiBzYW1wbGluZwoKTGV0J3MgbG9vayBhdCB0aGUgcGF0dGVybnMgaW4gc2VhcmNoIGJlaGF2aW9yLiBGaXJzdCwgbGV0J3MgbG9vayBhdCB0aGUgZGlzdGFuY2UgYmV0d2VlbiBzdWNjZXNzaXZlIGNob2ljZXMuCgpgYGB7cn0KI2NvbXBhcmUgdG8gcmFuZG9tCnNhbXBsZVNpemUgPC0gNDAwMDAwCnJhbmRvbURpc3RhbmNlREYgPC0gZGF0YS5mcmFtZSh4PXNhbXBsZSh4ID0gc2VxKDA6NyksIHNpemUgPSBzYW1wbGVTaXplLCByZXBsYWNlPVRSVUUpLCB5PXNhbXBsZSh4ID0gc2VxKDA6NyksIHNpemUgPSBzYW1wbGVTaXplLCByZXBsYWNlPVRSVUUpLCBlbnZpcm9ubWVudD1jKHJlcCgiUm91Z2giLHNhbXBsZVNpemUvMiksIHJlcCgiU21vb3RoIiwgc2FtcGxlU2l6ZS8yKSksIGNvbnRleHQgPSByZXAoYygnQ29uY2VwdHVhbCcsICdTcGF0aWFsJyksIHNhbXBsZVNpemUvMikpCnJhbmRvbURpc3RhbmNlREYgPC0gcmFuZG9tRGlzdGFuY2VERiAlPiUKICBtdXRhdGUoZGlzdGFuY2UgPSBhYnMoKHggLSBsYWcoeCxkZWZhdWx0ID0gTkEpKSArIGFicyh5IC0gbGFnKHksZGVmYXVsdCA9IE5BKSkgKSkKCgojQWRkIGNsYXNzaWZpY2F0aW9uIG9mIGNob2ljZXMgYXMgc3RheSwgbmVhciwgb3IgZmFyIGRlY2lzaW9ucwpsb2NhbGl0eURGIDwtZGRwbHkoZGYsIH5pZCt0cmlhbCtjb250ZXh0LCAgcGx5cjo6c3VtbWFyaXplLCBhdmdEaXN0YW5jZT1tZWFuKGRpc3RhbmNlLCBuYS5ybT1UKSkKbG9jYWxpdHlERiRjaG9pY2VUeXBlIDwtaWZlbHNlKGxvY2FsaXR5REYkYXZnRGlzdGFuY2U9PTAsICJTdGF5IiwgaWZlbHNlKGxvY2FsaXR5REYkYXZnRGlzdGFuY2U9PTEsICJOZWFyIiwgIkZhciIpKQpsb2NhbGl0eURGJGNob2ljZVR5cGUgPC0gZmFjdG9yKGxvY2FsaXR5REYkY2hvaWNlVHlwZSkKY2hvaWNlUHJvcCA8LSBkZHBseShuYS5vbWl0KGxvY2FsaXR5REYpLC4oaWQsY29udGV4dCksIGZ1bmN0aW9uKHgpIHdpdGgoeCxkYXRhLmZyYW1lKHRhYmxlKGNob2ljZVR5cGUpL2xlbmd0aChjaG9pY2VUeXBlKSwyKSkpCmNob2ljZVByb3AkY2hvaWNlVHlwZSA8LSBmYWN0b3IoY2hvaWNlUHJvcCRjaG9pY2VUeXBlLCBsZXZlbHM9YygiU3RheSIsICJOZWFyIiwgIkZhciIpKQpgYGAKTGV0J3MgZmlyc3QgZG8gYW4gQU5PVkEgaGVyZQoKYGBge3J9CiNUd28gd2F5IG1peGVkIEFOT1ZBOiBjb250ZXh0IGlzIHdpdGhpbiwgZW52aXJvbm1lbnQgaXMgYmV0d2VlbiAKZGQgPC1kZHBseShkZiwgfmlkK2Vudmlyb25tZW50K2NvbnRleHQsICBwbHlyOjpzdW1tYXJpemUsIGF2Z0Rpc3RhbmNlPW1lYW4oZGlzdGFuY2UsIG5hLnJtPVQpKQpkZCRpZCA8LSBmYWN0b3IoZGQkaWQpCnJlcy5hb3YgPC0gYW92KGF2Z0Rpc3RhbmNlIH4gZW52aXJvbm1lbnQqY29udGV4dCArIEVycm9yKGlkL2NvbnRleHQpLCBkYXRhPWRkKQphbm92YV9zdGF0cyhyZXMuYW92KQojIE5vdyBsZXQncyByZXBsaWNhdGUgdmlhIFJvYnVzdCBBTk9WQQpid3RyaW0oYXZnRGlzdGFuY2UgfiBlbnZpcm9ubWVudCpjb250ZXh0LCBpZCA9IGlkLCBkYXRhPWRkLCB0ciA9IDAuMikgI3VzaW5nIDIwJSB0cmltbWVkIG1lYW5zCnNwcGJhKGF2Z0Rpc3RhbmNlIH4gZW52aXJvbm1lbnQqY29udGV4dCwgaWQgPSBpZCwgZGF0YT1kZCkgI01haW4gZml4ZWQgZWZmZWN0CnNwcGJiKGF2Z0Rpc3RhbmNlIH4gZW52aXJvbm1lbnQqY29udGV4dCwgaWQgPSBpZCwgZGF0YT1kZCkgI1dpdGhpbi1zdWJlY3QgZWZmZWN0CiNOb3cgY29tcHV0ZSBCYXllcyBmYWN0b3IKYmYgPSBhbm92YUJGKGF2Z0Rpc3RhbmNlIH4gZW52aXJvbm1lbnQqY29udGV4dCtpZCwgIGRhdGE9ZGQsICB3aGljaFJhbmRvbT0iaWQiKQpiZgoKYGBgCgpMZXQncyBwbG90IHRoZSByZXN1bHRzCmBgYHtyfQoKY29udGV4dExhYmVscyA8LSBjKCdDb25jZXB0dWFsJyA9ICdDb25jZXB0dWFsXG5UYXNrJywgJ1NwYXRpYWwnID0gJ1NwYXRpYWxcblRhc2snLCAiUm91Z2giPSJSb3VnaCIsICJTbW9vdGgiPSJTbW9vdGgiKQpwNGFsdCA8LSBnZ3Bsb3QobmEub21pdChkZiksIGFlcyh4PWRpc3RhbmNlLCBmaWxsID0gY29udGV4dCwgY29sb3IgPSBjb250ZXh0KSkgKyAKICBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IC4uZGVuc2l0eS4uKjIwKSwgcG9zaXRpb24gPSAnZG9kZ2UnLCBiaW53aWR0aD0xLCBjb2xvcj0nYmxhY2snKSsKICBzdGF0X2RlbnNpdHkoZGF0YSA9IHJhbmRvbURpc3RhbmNlREYsIGFlcyh5ID0gLi5kZW5zaXR5Li4qMjApLCBnZW9tPSJsaW5lIixjb2xvcj0nYmxhY2snLCBzaXplID0gLjgsIGJ3ID0gMSkgKwogICNnZW9tX2RlbnNpdHkoZmlsbD1OQSwgc2l6ZSA9IDAuNykgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCIjMUI5RTc3IiwgIiNEOTVGMDIiLCAiQmxhY2siKSwgbmFtZT0iIikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjMUI5RTc3IiwgIiNEOTVGMDIiLCAiQmxhY2siKSwgbmFtZT0iIikgKwogIHlsYWIoIkNob2ljZXMgUGVyIFJvdW5kIikgKwogIHhsYWIoIkRpc3RhbmNlIEJldHdlZW4gQ2hvaWNlcyIpICsKICAjeGxpbSgwLDYpKwogIGZhY2V0X2dyaWQoY29udGV4dH5lbnZpcm9ubWVudCwgIGxhYmVsbGVyID0gYXNfbGFiZWxsZXIoY29udGV4dExhYmVscykpKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzY2FsZXM6OnByZXR0eV9icmVha3MobiA9IDUpKSsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDEwLCBieSA9IDIpKSsKICAjZ2d0aXRsZSgiTG9jYWxpdHkgb2YgU2FtcGxpbmciKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSdub25lJywgc3RyaXAuYmFja2dyb3VuZD1lbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5rZXk9ZWxlbWVudF9yZWN0KGNvbG9yPU5BKSkKcDRhbHQKYGBgCgpMZXQncyB0cnkgYSBkaWZmZXJlbnQgdmVyc2lvbiB3aGVyZSB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiB0YXNrIGFyZSBtb3JlIHNhbGllbnQKYGBge3J9Cgpjb250ZXh0TGFiZWxzIDwtIGMoJ0NvbmNlcHR1YWwnID0gJ0NvbmNlcHR1YWxcblRhc2snLCAnU3BhdGlhbCcgPSAnU3BhdGlhbFxuVGFzaycsICJSb3VnaCI9IlJvdWdoIiwgIlNtb290aCI9IlNtb290aCIpCmFubmRmPC1kYXRhLmZyYW1lKGRpc3RhbmNlID0gTkEsY29udGV4dCA9ICBOQSxlbnZpcm9ubWVudCA9IGZhY3RvcigiU21vb3RoIiwgbGV2ZWxzID0gYygiUm91Z2giLCAiU21vb3RoIikpLCB0ZXh0ID0gJ1JhbmRvbScsIGNvbG9yID0gJ2JsYWNrJykgI2ZvciBhbm5vdGF0aW9uCnA0YWx0IDwtIGdncGxvdChuYS5vbWl0KGRmKSwgYWVzKHg9ZGlzdGFuY2UsIGZpbGwgPSBjb250ZXh0LCBjb2xvciA9IGNvbnRleHQpKSArIAogIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gLi5kZW5zaXR5Li4qMjApLCBwb3NpdGlvbiA9ICdpZGVudGl0eScsIGJpbndpZHRoPTEsIGFscGhhID0gMC40KSsKICBzdGF0X2RlbnNpdHkoZGF0YSA9IHN1YnNldChyYW5kb21EaXN0YW5jZURGLCBjb250ZXh0ID09ICdDb25jZXB0dWFsJyksIGFlcyh5ID0gLi5kZW5zaXR5Li4qMjApLCBnZW9tPSJsaW5lIixjb2xvcj0nYmxhY2snLCBzaXplID0gLjgsIGJ3ID0gMSkgKwogICNnZW9tX2RlbnNpdHkoZmlsbD1OQSwgc2l6ZSA9IDAuNykgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCIjMUI5RTc3IiwgIiNEOTVGMDIiLCAiQmxhY2siKSwgbmFtZT0iVGFzayIpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiIzFCOUU3NyIsICIjRDk1RjAyIiwgIkJsYWNrIiksIG5hbWU9IlRhc2siKSArCiAgeWxhYigiQ2hvaWNlcyBQZXIgUm91bmQiKSArCiAgeGxhYigiRGlzdGFuY2UgQmV0d2VlbiBDaG9pY2VzIikgKwogICN4bGltKDAsNikrCiAgZmFjZXRfZ3JpZCh+ZW52aXJvbm1lbnQsICBsYWJlbGxlciA9IGFzX2xhYmVsbGVyKGNvbnRleHRMYWJlbHMpKSsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2NhbGVzOjpwcmV0dHlfYnJlYWtzKG4gPSA1KSkrCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAxMCwgYnkgPSAyKSkrCiAgI2dndGl0bGUoIkxvY2FsaXR5IG9mIFNhbXBsaW5nIikgKwogICNnZW9tX3RleHQoZGF0YSA9IGFubmRmLCB4ID0gMTAuNSwgeSA9IDUsIGxhYmVsID0gIlJhbmRvbSIsIGNvbG9yID0gJ2JsYWNrJywgc2l6ZSA9IDMuNSkrCiAgI2dlb21fc2VnbWVudChkYXRhID0gYW5uZGYsICB4ID0gOSwgeGVuZCA9IDEwLCB5ID0gNSwgeWVuZCA9IDUsY29sb3VyID0gImJsYWNrIiwgc2l6ZSA9IDEuMikrCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPWMoMSwxKSwgbGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDEsMSksIHN0cmlwLmJhY2tncm91bmQ9ZWxlbWVudF9ibGFuaygpLCBsZWdlbmQua2V5PWVsZW1lbnRfcmVjdChjb2xvcj1OQSkpCnA0YWx0CmBgYAoKUGFydGljaXBhbnRzIHNlYXJjaGVkIG92ZXIgbGFyZ2VyIGRpc3RhbmNlcyBpbiB0aGUgY29uY2VwdHVhbCB0YXNrIHRoYW4gdGhlIHNwYXRpYWwgdGFzayAoJHQoMTI4KT0tMy43JCwgJHA8LjAwMSQsICRkPTAuMyQsICRCRj01OSQpLiBUaGVyZSB3ZXJlIG5vIGRpZmZlcmVuY2VzIGFjcm9zcyBlbnZpcm9ubWVudHMgKCR0KDEyNyk9LTAuMyQsICRwPS43MjckLCAkZD0wLjA2JCwgJEJGPS4yMCQpLiBOb3RlIHRoYXQgZWFjaCB0cmlhbCBiZWdhbiBvbiBhIHJhbmRvbSBzZWxlY3RlZCBzdGltdWxpLiBTbyBzZWFyY2hpbmcgY2xvc2UgdG8gdGhlIHByZXZpb3VzIHNlbGVjdGlvbiBpcyBub3QgZHVlIHRvIGEgbGFjayBvZiBlZmZvcnQuICgkdCgxMjgpPS0xNi4yJCwgJHA8LjAwMSQsICRkPTEuNCQsICRCRj4xMDAkKQoKYGBge3IgZXZhbD1GLCBlY2hvPVR9CiNTdGF0aXN0aWNhbCB0ZXN0cyByZXBvcnRlZCBhYm92ZQpsb2NhbGl0eURGIDwtIGRkcGx5KGRmLCB+aWQrY29udGV4dCxwbHlyOjpzdW1tYXJpemUsIGF2Z0Rpc3RhbmNlPW1lYW4oZGlzdGFuY2UsIG5hLnJtPVQpKQp0dGVzdFByZXR0eShzdWJzZXQobG9jYWxpdHlERiwgY29udGV4dCA9PSAnU3BhdGlhbCcpJGF2Z0Rpc3RhbmNlLCBzdWJzZXQobG9jYWxpdHlERiwgY29udGV4dCA9PSAnQ29uY2VwdHVhbCcpJGF2Z0Rpc3RhbmNlLCB2YXIuZXF1YWw9VCwgcGFpcmVkPVQpCgpsb2NhbGl0eURGIDwtIGRkcGx5KGRmLCB+aWQrZW52aXJvbm1lbnQscGx5cjo6c3VtbWFyaXplLCBhdmdEaXN0YW5jZT1tZWFuKGRpc3RhbmNlLCBuYS5ybT1UKSkKdHRlc3RQcmV0dHkoc3Vic2V0KGxvY2FsaXR5REYsIGVudmlyb25tZW50ID09ICdTbW9vdGgnKSRhdmdEaXN0YW5jZSwgc3Vic2V0KGxvY2FsaXR5REYsIGVudmlyb25tZW50ID09ICdSb3VnaCcpJGF2Z0Rpc3RhbmNlLCB2YXIuZXF1YWw9VCkKCmxvY2FsaXR5REYgPC0gZGRwbHkoIGRmLCB+aWQsIHBseXI6OnN1bW1hcml6ZSwgYXZnRGlzdGFuY2U9bWVhbihkaXN0YW5jZSwgbmEucm09VCkpCnR0ZXN0UHJldHR5KG5hLm9taXQobG9jYWxpdHlERiRhdmdEaXN0YW5jZSksIG11ID0gbWVhbihyYW5kb21EaXN0YW5jZURGJGRpc3RhbmNlLCBuYS5ybT1UKSkKYGBgCgoKTm93IGxldCdzIGNsYXNzaWZ5IHRoZXNlIGNob2ljZXMgYXMgZWl0aGVyIGBTdGF5YCAoZGlzdGFuY2UgPSAwKSwgYE5lYXJgIChkaXN0YW5jZSA9IDEpLCBvciBgRmFyYCAoZGlzdGFuY2UgPjEpLgpgYGB7cn0KI2Nob2ljZSBwcm9wCmxvY2FsaXR5REYgPC1kZHBseShkZiwgfmlkK3RyaWFsK2NvbnRleHQsICBwbHlyOjpzdW1tYXJpemUsIGF2Z0Rpc3RhbmNlPW1lYW4oZGlzdGFuY2UsIG5hLnJtPVQpKQpsb2NhbGl0eURGJGRpc3RhbmNlIDwtbG9jYWxpdHlERiRhdmdEaXN0YW5jZQpyYW5kb21EaXN0YW5jZURGJGlkIDwtIDAKcmFuZG9tRGlzdGFuY2VERiRjb250ZXh0IDwtICdSYW5kb20nCmxvY2FsaXR5REYgPC0gcmJpbmQobG9jYWxpdHlERlssYyggImNvbnRleHQiLCAiZGlzdGFuY2UiLCAnaWQnKV0sIHJhbmRvbURpc3RhbmNlREZbLGMoICJjb250ZXh0IiwgImRpc3RhbmNlIiwgJ2lkJyldKQoKbG9jYWxpdHlERiRjaG9pY2VUeXBlIDwtaWZlbHNlKGxvY2FsaXR5REYkZGlzdGFuY2U9PTAsICJTdGF5IiwgaWZlbHNlKGxvY2FsaXR5REYkZGlzdGFuY2U9PTEsICJOZWFyIiwgIkZhciIpKQpsb2NhbGl0eURGJGNob2ljZVR5cGUgPC0gZmFjdG9yKGxvY2FsaXR5REYkY2hvaWNlVHlwZSkKCmNob2ljZVByb3AgPC0gZGRwbHkobmEub21pdChsb2NhbGl0eURGKSwuKGlkLGNvbnRleHQpLCAKICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbih4KSB3aXRoKHgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhLmZyYW1lKHRhYmxlKGNob2ljZVR5cGUpL2xlbmd0aChjaG9pY2VUeXBlKSwyKSkpCgpjaG9pY2VQcm9wJGNob2ljZVR5cGUgPC0gZmFjdG9yKGNob2ljZVByb3AkY2hvaWNlVHlwZSwgbGV2ZWxzPWMoIlN0YXkiLCAiTmVhciIsICJGYXIiKSkKCgpwNCA8LSBnZ3Bsb3QobmEub21pdChjaG9pY2VQcm9wKSwgYWVzKHg9Y2hvaWNlVHlwZSwgeSA9IEZyZXEqMjAsIGZpbGw9Y29udGV4dCwgY29sb3IgPSBjb250ZXh0KSkrCiAgc3RhdF9zdW1tYXJ5KGZ1bi55ID0gbWVhbixnZW9tPSdiYXInLCBwb3NpdGlvbj0nZG9kZ2UnLCBjb2xvcj0nYmxhY2snKSArCiAgc3RhdF9zdW1tYXJ5KGZ1bi5kYXRhID0gbWVhbl9zZSwgZ2VvbSA9ICJlcnJvcmJhciIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjkwKSwgd2lkdGggPSAwLjIsIGNvbG9yPSdibGFjaycgKSArCiAgI3NjYWxlX3lfY29udGludW91cyhsYWJlbHM9cGVyY2VudCkrCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoIiMxQjlFNzciLCAiI0Q5NUYwMiIsICJCbGFjayIpLCBuYW1lPSIiKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCIjMUI5RTc3IiwgIiNEOTVGMDIiLCAiQmxhY2siKSwgbmFtZT0iIikgKwogICNzY2FsZV9maWxsX3JpY2thbmRtb3J0eSgpKwogIHlsYWIoJ0Nob2ljZXMgUGVyIFJvdW5kIMKxU0UnKSsKICB4bGFiKCJDaG9pY2UgVHlwZSIpKwogICNmYWNldF9ncmlkKH5jb250ZXh0T3JkZXIpKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0gYygwLjA1LCAxKSwgbGVnZW5kLmp1c3RpZmljYXRpb249YygwLDEpLCBzdHJpcC5iYWNrZ3JvdW5kPWVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLmtleT1lbGVtZW50X3JlY3QoY29sb3I9TkEpKQpwNAoKYGBgCgpUaGlzIHNlZW1zIHRvIHBhaW50IHRoZSBzYW1lIHBpY3R1cmUgYXMgdGhlIGRpc3RhbmNlIGhpc3RvZ3JhbXMgYmVmb3JlLiBQYXJ0aWNpcGFudHMgbWFkZSBtb3JlIHN0YXkgY2hvaWNlcyBpbiB0aGUgc3BhdGlhbCB0YXNrIChgciB0dGVzdFByZXR0eShzdWJzZXQoY2hvaWNlUHJvcCwgY29udGV4dD09IkNvbmNlcHR1YWwiICYgY2hvaWNlVHlwZSA9PSJTdGF5IikkRnJlcSwgc3Vic2V0KGNob2ljZVByb3AsIGNvbnRleHQ9PSJTcGF0aWFsIiAmIGNob2ljZVR5cGUgPT0iU3RheSIpJEZyZXEsIHZhci5lcXVhbCA9IFQsIHBhaXJlZCA9IFQpYCkgYW5kIG1vcmUgZmFyIGNob2ljZXMgaW4gdGhlIGNvbmNlcHR1YWwgdGFzayAoYHIgdHRlc3RQcmV0dHkoc3Vic2V0KGNob2ljZVByb3AsIGNvbnRleHQ9PSJDb25jZXB0dWFsIiAmIGNob2ljZVR5cGUgPT0iRmFyIikkRnJlcSwgc3Vic2V0KGNob2ljZVByb3AsIGNvbnRleHQ9PSJTcGF0aWFsIiAmIGNob2ljZVR5cGUgPT0iRmFyIikkRnJlcSwgdmFyLmVxdWFsID0gVCwgcGFpcmVkID0gVClgKS4gVGhlcmUgd2VyZSBubyBkaWZmZXJlbmNlcyBpbiBuZWFyIGNob2ljZXMgKGByIHR0ZXN0UHJldHR5KHN1YnNldChjaG9pY2VQcm9wLCBjb250ZXh0PT0iQ29uY2VwdHVhbCIgJiBjaG9pY2VUeXBlID09Ik5lYXIiKSRGcmVxLCBzdWJzZXQoY2hvaWNlUHJvcCwgY29udGV4dD09IlNwYXRpYWwiICYgY2hvaWNlVHlwZSA9PSJOZWFyIikkRnJlcSwgdmFyLmVxdWFsID0gVCwgcGFpcmVkID0gVClgKS4KCiMjIyBTZWFyY2ggVHJhamVjdG9yaWVzCgpXZSBoYXZlIHRoaXMgcmVhbGx5IHJpY2ggZGF0YSBhYm91dCBob3cgcGFydGljaXBhbnRzIG5hdmlnYXRlZCB0aGUgc2VhcmNoIHNwYWNlLiBMZXQncyBmaXJzdCBsb29rIGF0IHRoZSBudW1iZXIgb2Ygc3RlcHMgcGFydGljaXBhbnRzIHRvb2sgYmVmb3JlIG1ha2luZyBhIHNlbGVjdGlvbgpgYGB7cn0KZGYkc3RlcHMgPC0gc2FwcGx5KGRmJHRyYWplY3RvcmllcywgZnVuY3Rpb24oaSkgbGVuZ3RoKGZyb21KU09OKGFzLmNoYXJhY3RlcihpKSkpKQp0cmFqREYgPC0gZGYlPiUgZ3JvdXBfYnkoaWQsY29udGV4dCkgJT4lIGRwbHlyOjpzdW1tYXJpemUoYXZnU3RlcHM9bWVhbihzdGVwcywgbmEucm09VCkpCnRyYWpDb250ZXh0REYgPC0gZGYlPiUgZ3JvdXBfYnkoaWQsY29udGV4dCkgJT4lIGRwbHlyOjpzdW1tYXJpemUoYXZnU3RlcHM9bWVhbihzdGVwcywgbmEucm09VCkpCnRyYUVudmpERiA8LSBkZiU+JSBncm91cF9ieShpZCxlbnZpcm9ubWVudCkgJT4lIGRwbHlyOjpzdW1tYXJpemUoYXZnU3RlcHM9bWVhbihzdGVwcywgbmEucm09VCkpCgpsZXZlbHMoZGYkY29udGV4dE9yZGVyKTwtIGMoIlNwYXRpYWwgRmlyc3QiLCAiQ29uY2VwdHVhbCBGaXJzdCIpCiNjb21wYXJpbmcgY29udGV4dApnZ3Bsb3QoZGYsIGFlcyh4ID0gY29udGV4dCwgeSA9IHN0ZXBzLCBmaWxsID0gY29udGV4dCkpKwogIHN0YXRfc3VtbWFyeShmdW4ueSA9IG1lYW4sIGdlb20gPSAiYmFyIiwgcG9zaXRpb24gPSAiZG9kZ2UiLCBjb2xvcj0nYmxhY2snKSArIAogIHN0YXRfc3VtbWFyeShmdW4uZGF0YSA9IG1lYW5fc2UsIGdlb20gPSAiZXJyb3JiYXIiLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC45MCksIHdpZHRoID0gMC4yLCBjb2xvciA9ICdibGFjaycgKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSdyaWdodCcsIHN0cmlwLmJhY2tncm91bmQ9ZWxlbWVudF9ibGFuaygpLCBsZWdlbmQua2V5PWVsZW1lbnRfcmVjdChjb2xvcj1OQSksIGxlZ2VuZC5iYWNrZ3JvdW5kPWVsZW1lbnRfYmxhbmsoKSwgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE2LCAgZmFtaWx5PSJzYW5zIikpKwogICNjb29yZF9jYXJ0ZXNpYW4oeWxpbT1jKDAsOCkpICsKICB4bGFiKCIiKSsKICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIkRhcmsyIiwgbmFtZT0iIikgKwogIGZhY2V0X2dyaWQofmNvbnRleHRPcmRlcikrCiAgeWxhYigiTWVhbiBOdW1iZXIgb2YgU3RlcHMgXHUwMEIxU0UiKQoKCm1lZGlhbnMgPC0gZGYlPiUgZ3JvdXBfYnkoZW52aXJvbm1lbnQsY29udGV4dCkgJT4lIGRwbHlyOjpzdW1tYXJpemUoc3RlcHM9bWVhbihzdGVwcywgbmEucm09VCkpCmNvbnRleHRMYWJlbHMgPC0gYygnQ29uY2VwdHVhbCcgPSAnQ29uY2VwdHVhbFxuVGFzaycsICdTcGF0aWFsJyA9ICdTcGF0aWFsXG5UYXNrJywgIlJvdWdoIj0iUm91Z2giLCAiU21vb3RoIj0iU21vb3RoIikKdHJhamVjdG9yeXBsb3QgPC0gZ2dwbG90KG5hLm9taXQoZGYpLCBhZXMoeD1zdGVwcywgZmlsbCA9IGNvbnRleHQsIGNvbG9yID0gY29udGV4dCkpICsgCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHkgPSAuLmRlbnNpdHkuLioyMCksIHBvc2l0aW9uID0gJ2RvZGdlJywgYmlud2lkdGg9MSwgY29sb3I9J2JsYWNrJykrCiAgI3N0YXRfZGVuc2l0eShkYXRhID0gYXMuZGF0YS5mcmFtZShyYW5kb21ERiksIGFlcyh2YWx1ZSksZ2VvbT0ibGluZSIsY29sb3I9J2JsYWNrJywgc2l6ZSA9IC44LCBsaW5ldHlwZT0nZGFzaGVkJykgKwogICNnZW9tX2RlbnNpdHkoZmlsbD1OQSwgc2l6ZSA9IDAuNykgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCIjMUI5RTc3IiwgIiNEOTVGMDIiLCAiQmxhY2siKSwgbmFtZT0iIikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjMUI5RTc3IiwgIiNEOTVGMDIiLCAiQmxhY2siKSwgbmFtZT0iIikgKwogIGdlb21fdmxpbmUoZGF0YSA9IG1lZGlhbnMsIGFlcyh4aW50ZXJjZXB0ID0gc3RlcHMpLCBsaW5ldHlwZSA9ICdkYXNoZWQnLCBzaXplID0uNykrCiAgeWxhYigiQ2hvaWNlcyBQZXIgUm91bmQiKSArCiAgeGxhYigiVHJhamVjdG9yeSBMZW5ndGgiKSArCiAgI3hsaW0oMCw2KSsKICBmYWNldF9ncmlkKGNvbnRleHR+ZW52aXJvbm1lbnQsIGxhYmVsbGVyID0gYXNfbGFiZWxsZXIoY29udGV4dExhYmVscykpKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzY2FsZXM6OnByZXR0eV9icmVha3MobiA9IDUpLCBsaW1pdHMgPSBjKDAsMjApKSsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDMsIGJ5ID0gMSkpKwogICNnZ3RpdGxlKCJMb2NhbGl0eSBvZiBTYW1wbGluZyIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249J25vbmUnLCBzdHJpcC5iYWNrZ3JvdW5kPWVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLmtleT1lbGVtZW50X3JlY3QoY29sb3I9TkEpKQp0cmFqZWN0b3J5cGxvdAoKYGBgClBhcnRpY2lwYW50cyBoYWQgbG9uZ2VyIHRyYWplY3RvcmllcyBpbiB0aGUgY29udGV4dHVhbCB0YXNrICgkdCgxMjgpPS0xMC43JCwgJHA8LjAwMSQsICRkPTEuMCQsICRCRj4xMDAkKSwgYWx0aG91Z2ggdGhlcmUgd2VyZSBubyBkaWZmZXJlbmNlcyBhY3Jvc3MgZW52aXJvbm1lbnRzICgkdCgxMjcpPTEuMyQsICRwPS4yMTMkLCAkZD0wLjIkLCAkQkY9LjM4JCkuIAoKCmBgYHtyIG1lc3NhZ2U9Rn0KdHRlc3RQcmV0dHkoc3Vic2V0KHRyYWpDb250ZXh0REYsIGNvbnRleHQgPT0gJ1NwYXRpYWwnKSRhdmdTdGVwcywgc3Vic2V0KHRyYWpDb250ZXh0REYsIGNvbnRleHQgPT0gJ0NvbmNlcHR1YWwnKSRhdmdTdGVwcywgdmFyLmVxdWFsPVQsIHBhaXJlZD1UKQp0dGVzdFByZXR0eShzdWJzZXQodHJhRW52akRGLCBlbnZpcm9ubWVudCA9PSAnU21vb3RoJykkYXZnU3RlcHMsIHN1YnNldCh0cmFFbnZqREYsIGVudmlyb25tZW50ID09ICdSb3VnaCcpJGF2Z1N0ZXBzLCB2YXIuZXF1YWw9VCkKYGBgCiMjIyBBdHRlbnRpb25hbCBCaWFzZXMKCkxldCdzIGFsc28gbG9vayBhdCB0aGUgdHJhamVjdG9yaWVzIGRlY29tcG9zZWQgaW50byB0aGUgdmVydGljYWwvc3RyaXBlIGZyZXF1ZW5jeSBkaW1lbnNpb24gdnMuIGhvcml6b250YWwvdGlsdCBkaW1lbnNpb24uIFRoZSBmaWd1cmUgYmVsb3cgc2hvd3MgdGhlIHByb3BvcnRpb24gb2YgcGFydGljaXBhbnQgaW5wdXRzIGNvcnJlc3BvbmRpbmcgdG8gZWFjaCBkaW1lbnNpb24sIHdoZXJlIHdlIHNlZSBhbiBoaWdoZXIgcHJvcG9ydGlvbiBvZiBpbnB1dHMgZ2l2ZW4gdG8gdGhlIHZlcnRpY2FsL3N0cmlwZSBmcmVxdWVuY3kgZGltZW5zaW9uIGluIGJvdGggdGFza3MsIHJlbGF0aXZlIHRvIHRoZSBob3Jpem9udGFsL3RpbHQgZGltZW5zaW9uLgpgYGB7cn0KI2NvbXBpbGUgdG90YWwgYnV0dG9uIHByZXNzZXNzIGZvciBlYWNoIGRpbWVuc2lvbgpkZiR0cmFqTGVmdCA8LSBzYXBwbHkoZGYkdHJhamVjdG9yaWVzLCBmdW5jdGlvbihpKSBzdW0oZnJvbUpTT04oYXMuY2hhcmFjdGVyKGkpKSA9PSAzNykpCmRmJHRyYWpVcCA8LSBzYXBwbHkoZGYkdHJhamVjdG9yaWVzLCBmdW5jdGlvbihpKSBzdW0oZnJvbUpTT04oYXMuY2hhcmFjdGVyKGkpKSA9PSAzOCkpCmRmJHRyYWpSaWdodCA8LSBzYXBwbHkoZGYkdHJhamVjdG9yaWVzLCBmdW5jdGlvbihpKSBzdW0oZnJvbUpTT04oYXMuY2hhcmFjdGVyKGkpKSA9PSAzOSkpCmRmJHRyYWpEb3duIDwtIHNhcHBseShkZiR0cmFqZWN0b3JpZXMsIGZ1bmN0aW9uKGkpIHN1bShmcm9tSlNPTihhcy5jaGFyYWN0ZXIoaSkpID09IDQwKSkKICAgICAgICAgICAgICAgICAgICAgIAp0cmFqRGlyREYgPC0gZGRwbHkoZGYsIH5pZCtjb250ZXh0K2Vudmlyb25tZW50LCBwbHlyOjpzdW1tYXJpemUsIGhvcml6b250YWwgPSAoc3VtKHRyYWpMZWZ0KStzdW0odHJhalJpZ2h0KSkvc3VtKHN0ZXBzKSwgdmVydGljYWwgPSAoc3VtKHRyYWpVcCkrc3VtKHRyYWpEb3duKSkvc3VtKHN0ZXBzKSkgI2NvbXB1dGUgYXZlcmFnZSBwZXIgcGFydGljaXBhbnQgcGVyIHRyaWFsCnRyYWpEaXJERiA8LSB0cmFqRGlyREYgICU+JSBnYXRoZXIoZGlyZWN0aW9uLCBwLCBob3Jpem9udGFsOnZlcnRpY2FsLCBmYWN0b3Jfa2V5PVRSVUUpICN3aWRlIHRvIGxvbmcKdHJhakRpckRGJGRpcmVjdGlvbiA8LSBmYWN0b3IodHJhakRpckRGJGRpcmVjdGlvbikKbGV2ZWxzKHRyYWpEaXJERiRkaXJlY3Rpb24pPC0gYygnSG9yaXpvbnRhbC9cblJvdGF0aW9uJywgJ1ZlcnRpY2FsL1xuU3RyaXBlcycpCnRyYWpEaXJERiRpZCA8LSBmYWN0b3IodHJhakRpckRGJGlkKQoKCiNwbG90CmlucHV0ZGlyIDwtIGdncGxvdCh0cmFqRGlyREYsIGFlcyh4ID0gZGlyZWN0aW9uLCB5ID0gcCwgZmlsbCA9IGNvbnRleHQpKSsKICBzdGF0X3N1bW1hcnkoZnVuLnkgPSBtZWFuLCBnZW9tID0gImJhciIsIHBvc2l0aW9uID0gImRvZGdlIiwgY29sb3I9J2JsYWNrJykgKyAKICBzdGF0X3N1bW1hcnkoZnVuLmRhdGEgPSBtZWFuX2NsX2Jvb3QsIGdlb20gPSAiZXJyb3JiYXIiLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC45MCksIHdpZHRoID0gMC4yLCBjb2xvciA9ICdibGFjaycgKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSdyaWdodCcsIHN0cmlwLmJhY2tncm91bmQ9ZWxlbWVudF9ibGFuaygpLCBsZWdlbmQua2V5PWVsZW1lbnRfcmVjdChjb2xvcj1OQSksIGxlZ2VuZC5iYWNrZ3JvdW5kPWVsZW1lbnRfYmxhbmsoKSkrCiAgI2Nvb3JkX2NhcnRlc2lhbih5bGltPWMoMCw4KSkgKwogIHhsYWIoIklucHV0IikrCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJEYXJrMiIsIG5hbWU9IlRhc2siKSArCiAgZmFjZXRfZ3JpZCh+ZW52aXJvbm1lbnQpKwogIHlsYWIoIlByb3BvcnRpb24gb2YgSW5wdXRzIFx1MDBCMSA5NSUgQ0kiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ3RvcCcpCmlucHV0ZGlyCmBgYApXZSBmb3JtYWxseSBkZWZpbmUgdGhlIGRpZmZlcmVuY2UgaW4gYXR0ZW50aW9uICRcRGVsdGFfe1x0ZXh0cm17ZGltfX0gPSBQKFx0ZXh0cm17dmVydGljYWwvc3RyaXBlIGZyZXF1ZW5jeX0pIC0gUChcdGV4dHJte2hvcml6b250YWwvdGlsdH0pJCwgd2hlcmUgcG9zaXRpdmUgdmFsdWVzIGluZGljYXRlIGEgc3Ryb25nZXIgYmlhcyB0b3dhcmRzIHRoZSB2ZXJ0aWNhbC9zdHJpcGUgZnJlcXVlbmN5IGRpbWVuc2lvbi4gUnVubmluZyBhIHR3by13YXkgbWl4ZWQgQU5PVkEgcmV2ZWFscyB0aGF0IGF0dGVudGlvbmFsIGJpYXMgd2FzIGluZmx1ZW5jZWQgYnkgdGhlIGludGVyYWN0aW9uIG9mIHRhc2sgb3JkZXIgYW5kIHRhc2sgKCRGKDEsMTI3KSA9IDguMSQsICAkcD0uMDA1JCwgJFxldGFeMj0uMDIkLCAkQkY+MTAwJCkuIAoKYGBge3J9CiNhZGQgdGFzayBvcmRlciBpbnRvIHRyYWpEaWZERgp0cmFqRGlyREYkRmlyc3RUYXNrIDwtIGRmW21hdGNoKHRyYWpEaXJERiRpZCwgZGYkaWQpLCJGaXJzdFRhc2siXQpkaWZmREYgPC0gZGRwbHkodHJhakRpckRGLCB+aWQrZW52aXJvbm1lbnQrY29udGV4dCtGaXJzdFRhc2ssIHBseXI6OnN1bW1hcml6ZSwgcGRpZmYgPSBkaWZmKHApKSAjY2FsY3VsYXRlIHRoZSBkaWZmZXJlbmNlIGluIHByb3BvcnRpb24gb2Yga2V5IHByZXNzZXMgb3ZlciBjb250ZXh0cyAocG9zaXRpdmUgaXMgbW9yZSB2ZXJ0aWNhbCwgd2hpbGUgbmVnYXRpdmUgaXMgbW9yZSBob3Jpem9udGFsICkKCiNBbm92YQpyZXMuYW92IDwtIGFvdihwIH4gY29udGV4dCpGaXJzdFRhc2sgKyBFcnJvcihpZC9jb250ZXh0KSwgZGF0YSA9ICBzdWJzZXQodHJhakRpckRGLCBkaXJlY3Rpb24gPT0nSG9yaXpvbnRhbC9cblJvdGF0aW9uJykpCmFub3ZhX3N0YXRzKHJlcy5hb3YpCiNSZXBsaWNhdGlvbiB3aXRoIHJvYnVzdCBBTk9WQQpid3RyaW0ocCB+IGNvbnRleHQqRmlyc3RUYXNrLCBpZCA9IGlkLCBkYXRhPXN1YnNldCh0cmFqRGlyREYsIGRpcmVjdGlvbiA9PSdIb3Jpem9udGFsL1xuUm90YXRpb24nKSwgdHIgPSAwLjIpICN1c2luZyAyMCUgdHJpbW1lZCBtZWFucwojQmF5ZXMgZmFjdG9yIG9mIEFOT1ZBCmludmlzaWJsZShiZiA8LSBhbm92YUJGKHAgfiAgY29udGV4dCpGaXJzdFRhc2sgLCAgZGF0YT1zdWJzZXQodHJhakRpckRGLCBkaXJlY3Rpb24gPT0nSG9yaXpvbnRhbC9cblJvdGF0aW9uJyksICB3aGljaFJhbmRvbT0iaWQiKSkKYmYKCmBgYAoKYGBge3J9CnBBdHRlbnRpb25UYXNrT3JkZXIgPC0gZ2dwbG90KGRpZmZERiwgYWVzKHggPSBjb250ZXh0LCB5ID0gcGRpZmYsIGZpbGwgPSBjb250ZXh0KSkrCiAgc3RhdF9zdW1tYXJ5KGZ1bi55ID0gbWVhbiwgZ2VvbT0nYmFyJywgY29sb3I9J2JsYWNrJykrCiAgc3RhdF9zdW1tYXJ5KGZ1bi5kYXRhID0gbWVhbl9jbF9ib290LCBnZW9tPSdlcnJvcmJhcicsIGNvbG9yID0gJ2JsYWNrJywgd2lkdGggPSAwLjIpKwogIGZhY2V0X2dyaWQofkZpcnN0VGFzaykrCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSdub25lJywgc3RyaXAuYmFja2dyb3VuZD1lbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5rZXk9ZWxlbWVudF9yZWN0KGNvbG9yPU5BKSwgbGVnZW5kLmJhY2tncm91bmQ9ZWxlbWVudF9ibGFuaygpKSsKICAjY29vcmRfY2FydGVzaWFuKHlsaW09YygwLDgpKSArCiAgeGxhYigiIikrCiAgeWxhYihleHByZXNzaW9uKCBEZWx0YVtkaW1dKSkrCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJEYXJrMiIsIG5hbWU9IlRhc2siKSAKcEF0dGVudGlvblRhc2tPcmRlcgpgYGAKIApXaGlsZSBwYXJ0aWNpcGFudHMgd2VyZSBtb3JlIGJpYXNlZCB0b3dhcmRzIHRoZSB2ZXJ0aWNhbC9zdHJpcGUgZnJlcXVlbmN5IGRpbWVuc2lvbiBpbiB0aGUgY29uY2VwdHVhbCB0YXNrIHdoZW4gdGhlIGNvbmNlcHR1YWwgdGFzayB3YXMgcGVyZm9ybWVkIGZpcnN0ICgkdCg2Nik9LTYuMCQsICRwPC4wMDEkLCAkZD0wLjckLCAkQkY+MTAwJCksIHRoZXNlIGRpZmZlcmVuY2VzIGRpc2FwcGVhcmVkIHdoZW4gdGhlIHNwYXRpYWwgdGFzayB3YXMgcGVyZm9ybWVkIGZpcnN0ICgkdCg2MSk9LTEuNiQsICRwPS4xMTgkLCAkZD0wLjIkLCAkQkY9LjQ1JCkuIApgYGB7ciBldmFsPUYsIGVjaG89VH0KdHRlc3RQcmV0dHkoc3Vic2V0KGRpZmZERiwgRmlyc3RUYXNrID09ICdDb25jZXB0dWFsIEZpcnN0JyAmIGNvbnRleHQgPT0gJ1NwYXRpYWwnKSRwZGlmZi0gc3Vic2V0KGRpZmZERiwgRmlyc3RUYXNrID09ICdDb25jZXB0dWFsIEZpcnN0JyAmIGNvbnRleHQgPT0gJ0NvbmNlcHR1YWwnKSRwZGlmZiwgbXU9MCkKdHRlc3RQcmV0dHkoc3Vic2V0KGRpZmZERiwgRmlyc3RUYXNrID09ICdTcGF0aWFsIEZpcnN0JyAmIGNvbnRleHQgPT0gJ1NwYXRpYWwnKSRwZGlmZi0gc3Vic2V0KGRpZmZERiwgRmlyc3RUYXNrID09ICdTcGF0aWFsIEZpcnN0JyAmIGNvbnRleHQgPT0gJ0NvbmNlcHR1YWwnKSRwZGlmZiwgbXU9MCkKYGBgCgpEb2VzIHVuZXF1YWwgcHJlZmVyZW5jZSBmb3Igb25lIG9mIHRoZSBmZWF0dXJlIGRpbWVuc2lvbnMgaW5mbHVlbmNlIHBlcmZvcm1hbmNlPyBUaGUgcmVzdWx0cyBhcmUgcHJlc2VudGVkIGluIHRoZSBmaWd1cmUgYmVsb3csIHdoZXJlIGVhY2ggcGFpciBvZiBkb3RzIGlzIGEgc2luZ2xlIHBhcnRpY2lwYW50LCBhbmQgdGhlIGNvbm5lY3RpbmcgbGluZSBzaG93cyB0aGUgY2hhbmdlIGluIHNjb3JlIGFuZCBjaGFuZ2UgaW4gYXR0ZW50aW9uYWwgYmlhcyAkXERlbHRhX3tcdGV4dHJte2RpbX19JCBhY3Jvc3MgdGFza3MuCmBgYHtyfQpwZXJmREY8LSBkZHBseShkZiwgfmlkK2Vudmlyb25tZW50K2NvbnRleHQrRmlyc3RUYXNrLCBwbHlyOjpzdW1tYXJpemUsIHNjb3JlID0gbWVhbih6KSkKZGlmZkRGJHNjb3JlIDwtIHBlcmZERiRzY29yZSAjdGFzayBzcGVjaWZpYyBzY29yZQoKcFNjb3JlQXR0ZW50aW9uIDwtIGdncGxvdChkaWZmREYsIGFlcyh4ID0gcGRpZmYsIHkgPSBzY29yZSwgY29sb3IgPWNvbnRleHQpKSsgCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuOCkgKyAKICBnZW9tX2xpbmUoYWVzKGdyb3VwPWlkKSwgY29sb3IgPSAnYmxhY2snLCBhbHBoYSA9IDAuMSkrCiAgZmFjZXRfZ3JpZCh+Rmlyc3RUYXNrKSsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJEYXJrMiIsIG5hbWU9IlRhc2siKSArCiAgI2dlb21fc21vb3RoKG1ldGhvZCA9ICdsbScpKwogeGxhYihleHByZXNzaW9uKCBEZWx0YVtkaW1dKSkrCiAgeWxhYignTWVhbiBTY29yZScpKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ndG9wJywgc3RyaXAuYmFja2dyb3VuZD1lbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5rZXk9ZWxlbWVudF9yZWN0KGNvbG9yPU5BKSkKcFNjb3JlQXR0ZW50aW9uCmBgYAoKV2UgZmluZCBhIG5lZ2F0aXZlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHNjb3JlIGFuZCBhdHRlbnRpb24gZm9yIHRoZSBjb25jZXB0dWFsIHRhc2sgb25seSBpbiB0aGUgY29uY2VwdHVhbCBmaXJzdCBvcmRlciAoJHJfe1x0YXV9PS0uMzEkLCAkcDwuMDAxJCwgJEJGPjEwMCQpLCBidXQgbm90IGluIHRoZSBzcGF0aWFsIGZpcnN0IG9yZGVyICgkcl97XHRhdX09LS4wNyQsICRwPS4zOTIkLCAkQkY9LjI0JCkuIFRoZXJlIHdlcmUgbm8gcmVsYXRpb25zaGlwcyBiZXR3ZWVuIHNjb3JlIGFuZCBhdHRlbnRpb24gaW4gdGhlIHNwYXRpYWwgdGFzayBpbiBlaXRoZXIgb3JkZXIgKHNwYXRpYWwgZmlyc3Q6ICRyX3tcdGF1fT0uMDMkLCAkcD0uNzM4JCwgJEJGPS4xNyQ7IGNvbmNlcHR1YWwgZmlyc3Q6ICRyX3tcdGF1fT0tLjAzJCwgJHA9Ljc1MCQsICRCRj0uMTckKS4gVGh1cywgc3Ryb25nIGF0dGVudGlvbmFsIGJpYXNlcyBwcmVkaWN0ZWQgbG93ZXIgc2NvcmUsIGJ1dCBvbmx5IGluIHRoZSBjb25jZXB0dWFsIGZpcnN0IHRhc2sgb3JkZXIuCgpgYGB7ciBldmFsPUYsIGVjaG89VH0KI3NwYXRpYWwgZmlyc3QKY29yVGVzdFByZXR0eShzdWJzZXQoZGlmZkRGLCBGaXJzdFRhc2sgPT0gJ1NwYXRpYWwgRmlyc3QnICYgY29udGV4dCA9PSAnU3BhdGlhbCcpJHBkaWZmLCBzdWJzZXQoZGlmZkRGLCBGaXJzdFRhc2sgPT0gJ1NwYXRpYWwgRmlyc3QnICYgY29udGV4dCA9PSAnU3BhdGlhbCcpJHNjb3JlLCBtZXRob2QgPSAna2VuZGFsbCcpCmNvclRlc3RQcmV0dHkoc3Vic2V0KGRpZmZERiwgRmlyc3RUYXNrID09ICdTcGF0aWFsIEZpcnN0JyAmIGNvbnRleHQgPT0gJ0NvbmNlcHR1YWwnKSRwZGlmZiwgc3Vic2V0KGRpZmZERiwgRmlyc3RUYXNrID09ICdTcGF0aWFsIEZpcnN0JyAmIGNvbnRleHQgPT0gJ0NvbmNlcHR1YWwnKSRzY29yZSwgbWV0aG9kID0gJ2tlbmRhbGwnKQoKY29yVGVzdFByZXR0eShzdWJzZXQoZGlmZkRGLCBGaXJzdFRhc2sgPT0gJ0NvbmNlcHR1YWwgRmlyc3QnICYgY29udGV4dCA9PSAnU3BhdGlhbCcpJHBkaWZmLCBzdWJzZXQoZGlmZkRGLCBGaXJzdFRhc2sgPT0gJ0NvbmNlcHR1YWwgRmlyc3QnICYgY29udGV4dCA9PSAnU3BhdGlhbCcpJHNjb3JlLCBtZXRob2QgPSAna2VuZGFsbCcpCmNvclRlc3RQcmV0dHkoc3Vic2V0KGRpZmZERiwgRmlyc3RUYXNrID09ICdDb25jZXB0dWFsIEZpcnN0JyAmIGNvbnRleHQgPT0gJ0NvbmNlcHR1YWwnKSRwZGlmZiwgc3Vic2V0KGRpZmZERiwgRmlyc3RUYXNrID09ICdDb25jZXB0dWFsIEZpcnN0JyAmIGNvbnRleHQgPT0gJ0NvbmNlcHR1YWwnKSRzY29yZSwgbWV0aG9kID0gJ2tlbmRhbGwnKQpgYGAKV2Ugbm93IGxvb2sgYXQgZGlmZmVyZW5jZXMgaW4gYXR0ZW50aW9uYWwgYmlhc2VzIGJldHdlZW4gdGFza3MuIFdlIGRlZmluZSAkXERlbHRhX3tcdGV4dHJte3Rhc2t9fSA9IFxEZWx0YV97XHRleHRybXtkaW19fV57XHRleHRybXtTcGF0aWFsfX0gLSBcRGVsdGFfe1x0ZXh0cm17ZGltfX1ee1x0ZXh0cm17Q29uY2VwdHVhbH19JC4gVGhpcyBkaWZmZXJlbmNlIG9mIGRpZmZlcmVuY2VzIGlzIGEgYml0IG1vcmUgZGlmZmljdWx0IHRvIGludGVycHJldCwgYnV0IHJlY2FsbCB0aGF0ICAkXERlbHRhX3tcdGV4dHJte2RpbX19JCB0ZW5kZWQgdG8gYmUgcG9zaXRpdmUsIHNpbmNlIHBhcnRpY2lwYW50cyBhdHRlbmRlZCBtb3JlIHRvd2FyZHMgdGhlIHZlcnRpY2FsL3N0cmlwZSBmcmVxdWVuY3kgZGltZW5zaW9uIGluIGJvdGggdGFza3MuIFRodXMsICRcRGVsdGFfe1x0ZXh0cm17dGFza319JCBpcyAqcG9zaXRpdmUqIGlmIHBhcnRpY2lwYW50cyB3ZXJlIG1vcmUgYmlhc2VkIHRvd2FyZHMgdGhlIHZlcnRpY2FsL3N0cmlwZSBmcmVxdWVuY3kgZGltZW5zaW9uIGluIHRoZSBzcGF0aWFsIHRhc2suIFZpY2UgdmVyc2EsICRcRGVsdGFfe1x0ZXh0cm17dGFza319JCBpcyAqbmVnYXRpdmUqIGlmIHBhcnRpY2lwYW50cyB3ZXJlIG1vcmUgYmlhc2VkIHRvd2FyZHMgIHRoZSB2ZXJ0aWNhbC9zdHJpcGUgZnJlcXVlbmN5IGRpbWVuc2lvbiBpbiB0aGUgY29uY2VwdHVhbCB0YXNrLiBMZXQncyBub3cgc2VlIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiAkXERlbHRhX3tcdGV4dHJte3Rhc2t9fSQgYW5kIGNoYW5nZSBpbiBzY29yZToKYGBge3J9CiNDb21wdXRlIGRlbHRhIHRhc2sKZGlmZkJ5Q29udGV4dCA8LSBkZHBseShkaWZmREYsIH5pZCtlbnZpcm9ubWVudCtGaXJzdFRhc2ssIHBseXI6OnN1bW1hcml6ZSwgcGRpZmYgPSBkaWZmKHBkaWZmKSkgI3N1bW1hcml6ZSBvdXQgY29udGV4dDsgcGRpZmYgc3BhdGlhbCAtIHBkaWZmIGNvbmNlcHR1YWwKI0FkZCBzY29yZSBkaWZmZXJlbmNlCnRhc2twZXJmREYgPC0gZGRwbHkoZGYsIH5pZCtlbnZpcm9ubWVudCtjb250ZXh0K0ZpcnN0VGFzaywgcGx5cjo6c3VtbWFyaXplLCBzY29yZSA9IG1lYW4oeikpICNtZWFuIHNjb3JlIGZvciBlYWNoIHRhc2sKdGFza1BlckRpZmZERiA8LSBkZHBseSh0YXNrcGVyZkRGLCB+aWQrZW52aXJvbm1lbnQsIHBseXI6OnN1bW1hcml6ZSwgc2NvcmVEaWZmID0gZGlmZihzY29yZSkpICNzcGF0aWFsIHNjb3JlICAtIGNvbmNlcHR1YWwgc2NvcmUKZGlmZkJ5Q29udGV4dCRzY29yZURpZmYgPC0gdGFza1BlckRpZmZERiRzY29yZURpZmYgI2FkZCB0byBkYXRhZnJhbWUKCgpwU2NvcmVEaWZmIDwtIGdncGxvdChkaWZmQnlDb250ZXh0LCBhZXMoeCA9IHBkaWZmLCB5ID0gc2NvcmVEaWZmLCBjb2xvciA9IEZpcnN0VGFzaywgZmlsbCA9IEZpcnN0VGFzaykpKyAKICBnZW9tX3BvaW50KGFscGhhID0gMC44KSArIAogICNnZW9tX2xpbmUoYWVzKGdyb3VwPWlkKSwgY29sb3IgPSAnYmxhY2snLCBhbHBoYSA9IDAuMSkrCiAgI2ZhY2V0X2dyaWQofkZpcnN0VGFzaykrCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiLCBuYW1lPSIiKSArCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJEYXJrMiIsIG5hbWU9IiIpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAnbG0nKSsKICB4bGFiKGV4cHJlc3Npb24oIERlbHRhW3Rhc2tdKSkrCiAgIHlsYWIoJ1NwYXRpYWwgU2NvcmUgLSBDb25jZXB0dWFsIFNjb3JlJykrCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSd0b3AnLCBzdHJpcC5iYWNrZ3JvdW5kPWVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLmtleT1lbGVtZW50X3JlY3QoY29sb3I9TkEpKQpwU2NvcmVEaWZmCmBgYApMb29raW5nIGZpcnN0IGF0IHBhcnRpY2lwYW50cyBpbiB0aGUgQ29uY2VwdHVhbCBGaXJzdCBjb25kaXRpb24sIHdlIGZpbmQgYW4gYW5lY2RvdGFsIHJlbGF0aW9uc2hpcCBiZXR3ZWVuICRcRGVsdGFfe1x0ZXh0cm17dGFza319JCBhbmQgZGlmZmVyZW5jZSBpbiBzY29yZSAoJHJfe1x0YXV9PS0uMjAkLCAkcD0uMDE5JCwgJEJGPTIuNCQpLiBUaGUgZGlyZWN0aW9uYWxpdHkgb2YgdGhpcyBlZmZlY3QgaXMgdGhhdCBwYXJ0aWNpcGFudHMgd2l0aCBhIHN0cm9uZ2VyIGJpYXMgdG93YXJkcyB0aGUgdmVydGljYWwvc3RyaXBlIGZyZXF1ZW5jeSBkaW1lbnNpb24gaW4gdGhlIGNvbmNlcHR1YWwgdGFzayB0ZW5kZWQgdG8gaGF2ZSBhIGxvd2VyIHNjb3JlIGluIHRoZSBjb25jZXB0dWFsIHRhc2sgcmVsYXRpdmUgdG8gdGhlIHNwYXRpYWwgdGFzay4gV2UgZmluZCBubyByZWxhdGlvbnNoaXAgYmV0d2VlbiAkXERlbHRhX3tcdGV4dHJte3Rhc2t9fSQgYW5kIGRpZmZlcmVuY2UgaW4gc2NvcmUgZm9yIHRoZSBTcGF0aWFsIEZpcnN0IGNvbmRpdGlvbiAoJHJfe1x0YXV9PS0uMDQkLCAkcD0uNjY2JCwgJEJGPS4xOCQpLiAgQW4gb3V0c3RhbmRpbmcgcXVlc3Rpb24gaXMgd2hldGhlciB0aGlzIHNoaWZ0IGluIGF0dGVudGlvbiBpcyByZXNwb25zaWJsZSBmb3IgdGhlIHRyYW5zZmVyIGVmZmVjdCwgb3IgaXMgbWVyZWx5IGFuIGFydGlmYWN0IG9mIHBhcnRpY2lwYW50cyBiZWluZyBtb3JlIGNhcGFibGUgb2YgbmF2aWdhdGluZyB0aGUgY29uY2VwdHVhbCBkb21haW4gYWZ0ZXIgcHJpb3IgZXhwZXJpZW5jZSB3aXRoIHRoZSBzcGF0aWFsIHRhc2tzLiBXaGlsZSB0aGVzZSBhbmFseXNlcyBwcm92aWRlIGZ1cnRoZXIgY2xhcmlmaWNhdGlvbiBhYm91dCB0aGUgcm9sZSBvZiBhdHRlbnRpb24sIHRoZSBleGFjdCByZWxhdGlvbnNoaXAgYmV0d2VlbiBhdHRlbnRpb24gKGFzIG1lYXN1cmVkIGJ5IGlucHV0IGZyZXF1ZW5jeSkgYW5kIGdlbmVyYWxpemF0aW9uIGlzIHBlcmhhcHMgb3V0c2lkZSB0aGUgc2NvcGUgb2Ygb3VyIGN1cnJlbnQgcGFwZXIuICAKCmBgYHtyIGV2YWw9RiwgZWNobz1UfQpjb3JUZXN0UHJldHR5KHN1YnNldChkaWZmQnlDb250ZXh0LCBGaXJzdFRhc2sgPT0gJ0NvbmNlcHR1YWwgRmlyc3QnKSRwZGlmZiwgc3Vic2V0KGRpZmZCeUNvbnRleHQsIEZpcnN0VGFzayA9PSAnQ29uY2VwdHVhbCBGaXJzdCcpJHNjb3JlRGlmZiwgbWV0aG9kID0gJ2tlbmRhbGwnKQpjb3JUZXN0UHJldHR5KHN1YnNldChkaWZmQnlDb250ZXh0LCBGaXJzdFRhc2sgPT0gJ1NwYXRpYWwgRmlyc3QnKSRwZGlmZiwgc3Vic2V0KGRpZmZCeUNvbnRleHQsIEZpcnN0VGFzayA9PSAnU3BhdGlhbCBGaXJzdCcpJHNjb3JlRGlmZiwgbWV0aG9kID0gJ2tlbmRhbGwnKQpgYGAKCiMjIyBFZmZpY2llbmN5CgpXZSBjYW4gYWxzbyBjb21wdXRlIHRoZSBlZmZpY2llbmN5IG9mIHRoZWlyIHRyYWplY3RvcmllcyBiYXNlZCBvbiAkXHRleHR7ZWZmaWNpZW5jeX0gPSBcZnJhY3tcdGV4dHtNYW5oYXR0YW4gRGlzdGFuY2UgZnJvbSBzdGFydCB0byBzZWxlY3Rpb259fXtcdGV4dHtTdGVwcyB0YWtlbn19JAoKYGBge3J9CmVmZmljZW5jeURGIDwtIGRkcGx5KGRmLCB+aWQrY29udGV4dCwgcGx5cjo6c3VtbWFyaXplLCBlZmZpY2llbmN5ID0gbWVhbihtb3ZlbWVudC9zdGVwcykpCgoKZWZmaWNpZW5jeVBsb3QgPC0gZ2dwbG90KGVmZmljZW5jeURGLCBhZXMoeCA9IGNvbnRleHQsIHkgPSBlZmZpY2llbmN5LCBjb2xvciA9IGNvbnRleHQsIGZpbGwgPSBjb250ZXh0KSkrCiAgZ2VvbV9ib3hwbG90KGZpbGw9TkEsIGNvbG9yID0gJ2JsYWNrJywgd2lkdGggPSAuMiwgb3V0bGllci5zaGFwZSA9IE5BKSsKICBnZW9tX3F1YXNpcmFuZG9tKGFscGhhID0gLjcpKwogIHN0YXRfc3VtbWFyeShmdW4ueSA9IG1lYW4sIGdlb20gPSAicG9pbnQiLGNvbG9yID0gJ2JsYWNrJywgZmlsbD1OQSwgc2hhcGUgPTIzLCBzaXplID0gMyApICsKICAjY29vcmRfY2FydGVzaWFuKHlsaW09YygwLDIpKSArCiAgeGxhYignJykrCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJEYXJrMiIsIG5hbWU9IiIpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJEYXJrMiIsIG5hbWU9IiIpICsKICB0aGVtZSggbGVnZW5kLnBvc2l0aW9uPSdub25lJywgc3RyaXAuYmFja2dyb3VuZD1lbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5iYWNrZ3JvdW5kPWVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLmtleT1lbGVtZW50X3JlY3QoY29sb3I9TkEpKSsKICB5bGFiKCJFZmZpY2llbmN5IFx1MDBCMVNFIikKZWZmaWNpZW5jeVBsb3QKYGBgClBhcnRpY2lwYW50cyBhcmUgY2xlYXJseSBsZXNzIGVmZmljaWVudCBpbiB0aGUgY29uY2VwdHVhbCB0YXNrIHRoYW4gdGhlIHNwYXRpYWwgdGFzayAoYCR0KDEyOCk9LTIwLjYkLCAkcDwuMDAxJCwgJGQ9MS45JCwgJEJGPjEwMCRgKS4KCmBgYHtyIGV2YWw9RiwgZWNobz1UfQp0dGVzdFByZXR0eShzdWJzZXQoZWZmaWNlbmN5REYsIGNvbnRleHQ9PSdDb25jZXB0dWFsJykkZWZmaWNpZW5jeSwgc3Vic2V0KGVmZmljZW5jeURGLCBjb250ZXh0PT0nU3BhdGlhbCcpJGVmZmljaWVuY3ksIHBhaXJlZD1UKQpgYGAKCk5vdyBsZXQncyBhc2ssIHdoYXQgZmFjdG9ycyBpbmZsdWVuY2UgdHJhamVjdG9yaWVzPyBEbyBsb25nZXIgdHJhamVjdG9yaWVzIG9idGFpbiBoaWdoZXIgcmV3YXJkcz8gWWVzIHRoZXkgZG8gKCRyPS4yMSQsICRwPC4wMDEkLCAkQkY+MTAwJCkuCmBgYHtyfQojc3RlcHMgYXMgYSBmdW5jdGlvbiBvZiBwcmV2aW91cyByZXdhcmQKcFRyYWpMZW5ndGhSZXdhcmQgPC0gZ2dwbG90KHN1YnNldChkZixzdGVwczw9MjApLCBhZXMoeCA9c3RlcHMsICB5ID0geiwgY29sb3IgPSBjb250ZXh0LCBmaWxsID0gY29udGV4dCkpKwogICNnZW9tX3Ntb290aChmaWxsPU5BKSsKICBzdGF0X3N1bW1hcnkoZnVuLnkgPSBtZWFuLCBnZW9tID0gInBvaW50IikgKyAKICBzdGF0X3N1bW1hcnkoZnVuLmRhdGEgPSBtZWFuX2NsX2Jvb3QsIGdlb20gPSAiZXJyb3JiYXIiKSArCiAgY29vcmRfY2FydGVzaWFuKHhsaW09YygwLDIwKSwgeWxpbT1jKDAsMTAwKSkgKyAjVHVrZXkgb3V0bGllciBjcml0ZXJpb24gaW5kaWNhdGVzIG91dGxpZXJzIGFib3ZlIDIwOyBtaW4oYm94cGxvdC5zdGF0cyhkZiRzdGVwcykkb3V0KQogICNmYWNldF9ncmlkKH5lbnZpcm9ubWVudCkrCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJEYXJrMiIsIG5hbWU9IlRhc2siKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiLCBuYW1lPSJUYXNrIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj1jKDEsMC4xKSxsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMSwwKSwgc3RyaXAuYmFja2dyb3VuZD1lbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5iYWNrZ3JvdW5kPWVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLmtleT1lbGVtZW50X3JlY3QoY29sb3I9TkEpKSsKICB5bGFiKCJSZXdhcmQgVmFsdWUgwrEgOTUlIENJIikrCiAgeGxhYignVHJhamVjdG9yeSBMZW5ndGgnKQpwVHJhakxlbmd0aFJld2FyZAoKYGBgCgoKV2UgY2FuIGFsc28gbG9vayBhdCB0aGUgZW50cm9weSBvZiBlYWNoIHRyYWplY3RvcnkgKGNvbXB1dGVkIG92ZXIgdGhlIGRpc3RyaWJ1dGlvbiBvZiBkaXJlY3Rpb25zIG1vdmVkKS4gSXQgc2VlbXMgbGlrZSBwYXJ0aWNpcGFudHMgaW4gdGhlIGNvbnRleHR1YWwgdGFzayBoYWQgaGlnaGVyIGVudHJvcHkgKGNvbnNpc3RlbnQgd2l0aCBsYXJnZXIgc3RlcCBzaXplcyBhbmQgbG93ZXIgZWZmaWNpZW5jeSksIGFuZCB0aGF0IGxvd2VyIGVudHJvcHkgcHJlZGljdHMgaGlnaGVyIHJld2FyZC4KYGBge3J9CmxpYnJhcnkoZW50cm9weSkKbXllbnQ8LWZ1bmN0aW9uKHgpewogIHJldHVybihlbnRyb3B5LmVtcGlyaWNhbCh0YWJsZSh4KSkpCn0KZGYkdHJhakVudHJvcHkgPC0gc2FwcGx5KGRmJHRyYWplY3RvcmllcywgZnVuY3Rpb24oaSkgICBteWVudChmcm9tSlNPTihhcy5jaGFyYWN0ZXIoaSkpKSkKCmdncGxvdChkZiwgYWVzKHggPSBjb250ZXh0LCB5ID0gdHJhakVudHJvcHksIGZpbGwgPSBjb250ZXh0KSkrCiAgc3RhdF9zdW1tYXJ5KGZ1bi55ID0gbWVhbixnZW9tPSdiYXInLCBwb3NpdGlvbj0nZG9kZ2UnLCBjb2xvcj0nYmxhY2snKSArCiAgc3RhdF9zdW1tYXJ5KGZ1bi5kYXRhID0gbWVhbl9zZSwgZ2VvbSA9ICJlcnJvcmJhciIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjkwKSwgd2lkdGggPSAwLjIsIGNvbG9yPSdibGFjaycgKSArCiAgI3NjYWxlX3lfY29udGludW91cyhsYWJlbHM9cGVyY2VudCkrCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoIiMxQjlFNzciLCAiI0Q5NUYwMiIpLCBuYW1lPSIiKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCIjMUI5RTc3IiwgIiNEOTVGMDIiKSwgbmFtZT0iIikgKwogIGZhY2V0X2dyaWQofmVudmlyb25tZW50KQogIApnZ3Bsb3Qoc3Vic2V0KGRmLCB0cmFqRW50cm9weT4wKSwgYWVzKHggPSB0cmFqRW50cm9weSwgeSA9IHosIGNvbG9yID0gY29udGV4dCkpKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjA1KSsKICBnZW9tX3Ntb290aChtZXRob2QgPSAnbG0nKSsKICAjc3RhdF9zdW1tYXJ5KGZ1bi55ID0gbWVhbiwgZ2VvbSA9ICJwb2ludCIpICsgCiAgI3N0YXRfc3VtbWFyeShmdW4uZGF0YSA9IG1lYW5fY2xfYm9vdCwgZ2VvbSA9ICJlcnJvcmJhciIpICsKICB4bGFiKCdFbnRyb3B5JykrIHlsYWIoJ1Jld2FyZCBWYWx1ZScpKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCIjMUI5RTc3IiwgIiNEOTVGMDIiKSwgbmFtZT0iIikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiIzFCOUU3NyIsICIjRDk1RjAyIiksIG5hbWU9IiIpICsKICBmYWNldF9ncmlkKH5lbnZpcm9ubWVudCkKICAKCmBgYAoKSG93IHdlcmUgYm90aCBkaXN0YW5jZSBhbmQgdHJhamVjdG9yeSBsZW5ndGggaW5mbHVlbmNlZCBieSB0aGUgKnByZXZpb3VzKiByZXdhcmQgdmFsdWU/CmBgYHtyfQojcmV3YXJkIGFuZCBkaXN0YW5jZQojY29yVGVzdFByZXR0eShuYS5vbWl0KGRmKSRkaXN0YW5jZSwgbmEub21pdChkZikkcHJldmlvdXNSZXdhcmQpCnA1IDwtIGdncGxvdChuYS5vbWl0KGRmKSwgYWVzKHg9ZGlzdGFuY2UsIHkgPSBwcmV2aW91c1Jld2FyZCwgY29sb3IgPSBjb250ZXh0LCBmaWxsPWNvbnRleHQpKSArCiAgI2dlb21fY291bnQoYWxwaGE9MC4yLCBzaG93LmxlZ2VuZCA9IEYsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGg9MC4xKSkrCiAgI3NjYWxlX3NpemVfYXJlYShtYXhfc2l6ZSA9IDUpKwogICNnZW9tX2ppdHRlcihhbHBoYT0wLjA1LCBzaXplPTAuNSkrCiAgI2dlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIpICsKICBzdGF0X3N1bW1hcnkoZnVuLnkgPSBtZWFuLCBnZW9tID0gJ2xpbmUnLCBzaXplPTEpKwogIHN0YXRfc3VtbWFyeShmdW4uZGF0YSA9IG1lYW5fc2UsIGdlb20gPSAncmliYm9uJywgYWxwaGEgPSAwLjcsIGNvbG9yPU5BKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICBsYWJzKHk9J1ByZXZpb3VzIFJld2FyZCBWYWx1ZScsIHggPSAnRGlzdGFuY2UgQmV0d2VlbiBTZWxlY3Rpb25zJykrCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNjYWxlczo6cHJldHR5X2JyZWFrcyhuID0gNSkpKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gJ0RhcmsyJywgbmFtZT0iVGFzayIpKwogIHNjYWxlX2ZpbGxfYnJld2VyKCBwYWxldHRlID0gJ0RhcmsyJywgbmFtZT0iVGFzayIpKwogICNjb29yZF9mbGlwKCkrCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPWMoMSwxKSwgbGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDEsMSksIHN0cmlwLmJhY2tncm91bmQ9ZWxlbWVudF9ibGFuaygpLCBsZWdlbmQua2V5PWVsZW1lbnRfcmVjdChjb2xvcj1OQSksIGxlZ2VuZC5iYWNrZ3JvdW5kPWVsZW1lbnRfYmxhbmsoKSkKcDUKYGBgCkl0IHNlZW1zIGxpa2UgcGFydGljaXBhbnRzIG1vdmUgZnVydGhlciBhd2F5IGZyb20gdGhlaXIgcHJldmlvdXMgc2VsZWN0aW9uIHdoZW4gdGhlIHJld2FyZCB2YWx1ZSB3YXMgbG93ICgkcj0tLjY2JCwgJHA8LjAwMSQsICRCRj4xMDAkKSwgc3VnZ2VzdGluZyBiYXNpYyBldmlkZW5jZSBvZiBnZW5lcmFsaXphdGlvbiBiZWhhdmlvci4KCkxldCdzIHJ1biBhIG1peGVkIG1vZGVsIG9uIHRoZXNlIHJlc3VsdHMKCmBgYHtyfQojTWl4ZWQgZWZmZWN0cyBtb2RlbGluZwojUHJldmlvdXMgcmV3YXJkIHZhbHVlIGFuZCBkaXN0YW5jZSBiZXR3ZWVuIHNlbGVjdGlvbnMKcHJpb3IgPC0gYyhzZXRfcHJpb3IoIm5vcm1hbCgwLDEpIiwgY2xhc3MgPSAiYiIpLHNldF9wcmlvcigibm9ybWFsKDAsMSkiLCBjbGFzcyA9ICJzZCIpKQpkaXN0YW5jZVJld2FyZE1NIDwtIHJ1bl9tb2RlbChicm0oZGlzdGFuY2UgfiAwKyBpbnRlcmNlcHQrIHByZXZpb3VzUmV3YXJkK2NvbnRleHQrcHJldmlvdXNSZXdhcmQqY29udGV4dCArKDErcHJldmlvdXNSZXdhcmQqY29udGV4dHxpZCksIGRhdGE9c3Vic2V0KGRmLCAhaXMubmEoZGYkZGlzdGFuY2UpKSwgcHJpb3IgPSBwcmlvcixjb3Jlcz00LCAgaXRlciA9IDQwMDAsIHdhcm11cCA9IDEwMDAsIGNvbnRyb2wgPSBsaXN0KGFkYXB0X2RlbHRhID0gMC45OSkpLCBtb2RlbE5hbWUgPSAnZGlzdGFuY2VSZXdhcmRNTScpCiN0YWJfbW9kZWwoZGlzdGFuY2VSZXdhcmRNTSkgI1JlYWxseSBzbG93IQpmaXhlZFRlcm1zIDwtIGZpeGVmKGRpc3RhbmNlUmV3YXJkTU0pI0xvb2sgYXQgZml4ZWQgdGVybXMKCiNOb3cgZ2VuZXJhdGUgcHJlZGljdGlvbnMsIHJlbW92aW5nIGlkIGFzIGEgcmFuZG9tIGVmZmVjdAp4c2VxIDwtIHNlcSgwLDEwMCkKbmV3ZGF0IDwtZGF0YS5mcmFtZShjb250ZXh0ID0gcmVwKGMoIkNvbmNlcHR1YWwiLCJTcGF0aWFsIiksIGVhY2g9MTAxKSwgcHJldmlvdXNSZXdhcmQgPSByZXAoeHNlcSwyKSkKcHJlZHMgPC0gZml0dGVkKGRpc3RhbmNlUmV3YXJkTU0sIHJlX2Zvcm11bGEgPSBOQSwgbmV3ZGF0YSA9IG5ld2RhdCwgcHJvYnMgPSBjKDAuMDI1LCAwLjk3NSkpCiNjcmVhdGUgbmV3IGZpeGVkIGVmZmVjdHMgZGF0YWZyYW1lCmZpeGVkREYgPC0gZGF0YS5mcmFtZShjb250ZXh0ID0gcmVwKGMoIkNvbmNlcHR1YWwiLCJTcGF0aWFsIiksIGVhY2g9MTAxKSwgcHJldmlvdXNSZXdhcmQgPSByZXAoeHNlcSwyKSwKICAgICAgICAgICAgICAgICAgICAgIGRpc3RhbmNlID0gcHJlZHNbLDFdLCBsb3dlciA9IHByZWRzWywzXSwgdXBwZXIgPSBwcmVkc1ssNF0gKQoKcDVhbHQgPC0gZ2dwbG90KHN1YnNldChkZiwgIWlzLm5hKGRmJGRpc3RhbmNlKSksIGFlcyhwcmV2aW91c1Jld2FyZCwgZGlzdGFuY2UsIGNvbG9yID0gY29udGV4dCwgZmlsbCAgPSBjb250ZXh0KSkgKwogICNnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBtZWFuKHJhbmRvbURpc3RhbmNlREYkZGlzdGFuY2UsIG5hLnJtPVQgKSwgc2l6ZSA9IDEsIGNvbG9yID0gJ2JsYWNrJywgbGluZXR5cGU9J2Rhc2hlZCcpKyAKICBnZW9tX2xpbmUoZGF0YSA9IGZpeGVkREYsICBzaXplID0gMSkrICNHUCBpcwogIGdlb21fcmliYm9uKGRhdGEgPSBmaXhlZERGLCBhZXMoeW1pbj1sb3dlciwgeW1heCA9IHVwcGVyKSwgY29sb3IgPSBOQSwgYWxwaGEgPSAwLjQgKSsKICBzdGF0X3N1bW1hcnkoZnVuLnk9bWVhbixnZW9tPSdwb2ludCcsIGFscGhhID0gMC44KSsKICAjZ2VvbV9hYmxpbmUoc2xvcGUgPSAxLCBsaW5ldHlwZSA9ICdkYXNoZWQnKSsKICAjY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDAsMTAwKSkrCiAgeGxpbShjKDAsMTAwKSkrCiAgdGhlbWVfY2xhc3NpYygpKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gJ0RhcmsyJywgbmFtZT0iVGFzayIpKwogIHNjYWxlX2ZpbGxfYnJld2VyKCBwYWxldHRlID0gJ0RhcmsyJywgbmFtZT0iVGFzayIpKwogICNmYWNldF9ncmlkKH5jb250ZXh0LCBsYWJlbGxlciA9IGFzX2xhYmVsbGVyKGNvbnRleHRMYWJlbHMpICkrCiAgeGxhYigiUHJldmlvdXMgUmV3YXJkIFZhbHVlIikrCiAgeWxhYigiRGlzdGFuY2UgQmV0d2VlbiBTZWxlY3Rpb25zIikrCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gNTAsIHkgPSA4LCBsYWJlbCA9ICJwYXN0ZShpdGFsaWMoYilbcHJldlJld2FyZF0gLCBcIiA9IC0wLjA2LCA5NSUgSFBEOiBbLTAuMDYsIC0wLjA2XVwiKSIsIHBhcnNlID0gVFJVRSkrCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPWMoMCwgMCksIGxlZ2VuZC5qdXN0aWZpY2F0aW9uPWMoMCwwKSwgc3RyaXAuYmFja2dyb3VuZD1lbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5rZXk9ZWxlbWVudF9ibGFuaygpLCBsZWdlbmQuYmFja2dyb3VuZD1lbGVtZW50X2JsYW5rKCkpCnA1YWx0CgpgYGAKCkF0IHRoZXIgc2FtZSB0aW1lLCBwYXJ0aWNpcGFudHMgYWxzbyBtb3ZlZCBmdXRoZXIgYXdheSBmcm9tIHRoZWlyIGluaXRpYWwgc3RhcnRpbmcgcG9pbnQgYWZ0ZXIgb2JzZXJ2aW5nIGxhcmdlciByZXdhcmQgdmFsdWVzIChgciBjb3JUZXN0UHJldHR5KG5hLm9taXQoZGYpJG1vdmVtZW50LCBuYS5vbWl0KGRmKSRwcmV2aW91c1Jld2FyZCwgbWV0aG9kPSdrZW5kYWxsJylgKS4gTm90ZSB0aGF0IHRoZSB0aGVyZSB3YXMgYSByYW5kb20gc3RhcnRpbmcgcG9zaXRpb24gYXQgdGhlIGJlZ2lubmluZyBvZiBlYWNoIHRyaWFsLiBTbyB0aGUgc3RhcnRpbmcgcG9pbnQgaXMgbm90IHRoZSBzYW1lIGFzIHRoZSBwcmV2aW91cyBzZWxlY3Rpb24uIEEgc21hbGwgZGlzdGFuY2UgZnJvbSB0aGUgaW5pdGlhbCBzdGFydGluZyBwb2ludCBpcyBpbmRpY2F0aXZlIG9mIHJhbmRvbSBzZWFyY2ggYmVoYXZpb3IsIHV0aWxpemluZyB0aGUgcmFuZG9tbmVzcyBvZiB0aGUgaW5pdGlhbGl6YXRpb24uIFRoZSB0cmVuZCBpbmRpY2F0ZXMgdGhhdCBwYXJ0aWNpcGFudHMgbWFkZSBhIGxhcmdlciBlZmZvcnQgdG8gc2VhcmNoIGluIGEgZGlyZWN0ZWQgZmFzaGlvbiBhZnRlciBvYnNlcnZpbmcgbGFyZ2UgcmV3YXJkIHZhbHVlcwoKYGBge3J9CgpwcmlvciA8LSBjKHNldF9wcmlvcigibm9ybWFsKDAsMSkiLCBjbGFzcyA9ICJiIiksc2V0X3ByaW9yKCJub3JtYWwoMCwxKSIsIGNsYXNzID0gInNkIikpCmRpc3RhbmNlSW5pdGlhbE1NIDwtIHJ1bl9tb2RlbChicm0obW92ZW1lbnQgfjAgKyBpbnRlcmNlcHQgK3ByZXZpb3VzUmV3YXJkKmNvbnRleHQgKygxK3ByZXZpb3VzUmV3YXJkKmNvbnRleHxpZCksIGRhdGE9c3Vic2V0KGRmLCAhaXMubmEoZGYkbW92ZW1lbnQpKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3IgPSBwcmlvciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3Jlcz00LCAgaXRlciA9IDQwMDAsIHdhcm11cCA9IDEwMDAsIGNvbnRyb2wgPSBsaXN0KGFkYXB0X2RlbHRhID0gMC45OSkpLCBtb2RlbE5hbWUgPSAnZGlzdGFuY2VJbml0aWFsTU0nKQojYmF5ZXNfUjIoZGlzdGFuY2VJbml0aWFsTU0pCiN0YWJfbW9kZWwoZGlzdGFuY2VJbml0aWFsTU0pCmZpeGVkVGVybXMgPC0gZml4ZWYoZGlzdGFuY2VJbml0aWFsTU0pI0xvb2sgYXQgZml4ZWQgdGVybXMKCiNOb3cgZ2VuZXJhdGUgcHJlZGljdGlvbnMsIHJlbW92aW5nIGlkIGFzIGEgcmFuZG9tIGVmZmVjdAp4c2VxIDwtIHNlcSgxLDEwMCkKbmV3ZGF0IDwtZGF0YS5mcmFtZShjb250ZXh0ID0gcmVwKGMoIkNvbmNlcHR1YWwiLCJTcGF0aWFsIiksIGVhY2g9MTAwKSwgcHJldmlvdXNSZXdhcmQgPSByZXAoeHNlcSwyKSkKcHJlZHMgPC0gZml0dGVkKGRpc3RhbmNlSW5pdGlhbE1NLCByZV9mb3JtdWxhID0gTkEsIG5ld2RhdGEgPSBuZXdkYXQsIHByb2JzID0gYygwLjAyNSwgMC45NzUpKQojY3JlYXRlIG5ldyBmaXhlZCBlZmZlY3RzIGRhdGFmcmFtZQpmaXhlZERGIDwtIGRhdGEuZnJhbWUoY29udGV4dCA9IHJlcChjKCJDb25jZXB0dWFsIiwiU3BhdGlhbCIpLCBlYWNoPTEwMCksIHByZXZpb3VzUmV3YXJkID0gcmVwKHhzZXEsMiksCiAgICAgICAgICAgICAgICAgICAgICBtb3ZlbWVudCA9IHByZWRzWywxXSwgbG93ZXIgPSBwcmVkc1ssM10sIHVwcGVyID0gcHJlZHNbLDRdICkKCnA2IDwtIGdncGxvdChzdWJzZXQoZGYsICFpcy5uYShkZiRtb3ZlbWVudCkpLCBhZXMocHJldmlvdXNSZXdhcmQsIG1vdmVtZW50LCBjb2xvciA9IGNvbnRleHQsIGZpbGwgID0gY29udGV4dCkpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBtZWFuKHJhbmRvbURpc3RhbmNlREYkZGlzdGFuY2UsIG5hLnJtPVQgKSwgc2l6ZSA9IDEsIGNvbG9yID0gJ2JsYWNrJywgbGluZXR5cGU9J2Rhc2hlZCcpKyAKICBnZW9tX2xpbmUoZGF0YSA9IGZpeGVkREYsICBzaXplID0gMSkrICNHUCBpcwogIGdlb21fcmliYm9uKGRhdGEgPSBmaXhlZERGLCBhZXMoeW1pbj1sb3dlciwgeW1heCA9IHVwcGVyKSwgY29sb3IgPSBOQSwgYWxwaGEgPSAwLjQgKSsKICBzdGF0X3N1bW1hcnkoZnVuLnk9bWVhbixnZW9tPSdwb2ludCcsIGFscGhhID0gMC44KSsKICAjZ2VvbV9hYmxpbmUoc2xvcGUgPSAxLCBsaW5ldHlwZSA9ICdkYXNoZWQnKSsKICAjY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDAsMTAwKSkrCiAgeGxpbShjKDAsMTAwKSkrCiAgdGhlbWVfY2xhc3NpYygpKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gJ0RhcmsyJywgbmFtZT0iVGFzayIpKwogIHNjYWxlX2ZpbGxfYnJld2VyKCBwYWxldHRlID0gJ0RhcmsyJywgbmFtZT0iVGFzayIpKwogICNmYWNldF9ncmlkKH5jb250ZXh0LCBsYWJlbGxlciA9IGFzX2xhYmVsbGVyKGNvbnRleHRMYWJlbHMpICkrCiAgeGxhYigiUHJldmlvdXMgUmV3YXJkIFZhbHVlIikrCiAgeWxhYigiRGlzdGFuY2UgRnJvbSBJbml0aWFsIFBvc2l0aW9uIikrCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gNTAsIHkgPSA4LCBsYWJlbCA9ICJwYXN0ZShpdGFsaWMoYilbcHJldlJld2FyZF0gLCBcIiA9IDAuMDEsIDk1JSBIUEQ6IFswLjAxLCAwLjAxXVwiKSIsIHBhcnNlID0gVFJVRSkrCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPWMoMCwgMC43KSwgbGVnZW5kLmp1c3RpZmljYXRpb249YygwLDEpLCBzdHJpcC5iYWNrZ3JvdW5kPWVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLmtleT1lbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5iYWNrZ3JvdW5kPWVsZW1lbnRfYmxhbmsoKSkKcDYKYGBgCgoKIyMgSGVhdG1hcCBvZiBjbGlja3MKCkxldCdzIGxvb2sgYXQgYW55IHBhdHRlcm5zIGluIGhvdyBwZW9wbGUgc2VhcmNoZWQgdGhlIGlucHV0IHNwYWNlLiBVbnN1cnByaXNpbmdseSwgdGhlcmUgaXMgYSBwcmVmZXJlbmNlIGZvciBjb3JuZXJzIGFuZCBlZGdlcy4gWWVsbG93IGlzIG1hcHBlZCB0byByYW5kb20gY2hhbmNlLCBzbyBvcmFuZ2UgYW5kIHJlZCBhcmUgaGlnaGVyIHRoYW4gY2hhbmNlLCB3aGlsZSBncmVlbiBhbmQgYmx1ZSBhcmUgbG93ZXIgdGhhbiBjaGFuY2UuCgpgYGB7cn0KI0hlYXRtYXAgb2YgY2xpY2tzCiNzcGF0aWFsIGFuZCBzcGF0aWFsCnNwYXRpYWxDb3VudHMgPC0gZGRwbHkoc3Vic2V0KGRmLCBjb250ZXh0ID09ICdTcGF0aWFsJyksIC4oeCwgeSksIG5yb3cpCm5hbWVzKHNwYXRpYWxDb3VudHMpIDwtIGMoIlgiLCAiWSIsICJGcmVxIikKc3BhdGlhbENvdW50cyRQcm9iIDwtIHNwYXRpYWxDb3VudHMkRnJlcSAvIHN1bShzcGF0aWFsQ291bnRzJEZyZXEpCgpjb25jZXB0Q291bnRzIDwtIGRkcGx5KHN1YnNldChkZiwgY29udGV4dCA9PSAnQ29uY2VwdHVhbCcpLCAuKHgsIHkpLCBucm93KQpuYW1lcyhjb25jZXB0Q291bnRzKSA8LSBjKCJYIiwgIlkiLCAiRnJlcSIpCmNvbmNlcHRDb3VudHMkUHJvYiA8LSBjb25jZXB0Q291bnRzJEZyZXEgLyBzdW0oY29uY2VwdENvdW50cyRGcmVxKQoKbWF4RnJlcSA8LSBtYXgobWF4KHNwYXRpYWxDb3VudHMkUHJvYiksIG1heChjb25jZXB0Q291bnRzJFByb2IpKQoKaGVhdG1hcFNwYXRpYWwgPC0gZ2dwbG90KHNwYXRpYWxDb3VudHMsIGFlcyh4PVgsIHkgPSBZLCBmaWxsPVByb2IpKSArCiAgZ2VvbV90aWxlKCkrCiAgc2NhbGVfZmlsbF9kaXN0aWxsZXIocGFsZXR0ZSA9ICJTcGVjdHJhbCIsIG5hbWUgPSAnRnJlcScsIHZhbHVlcz1yZXNjYWxlKGMoMCwxLzY0LG1heEZyZXEpKSxsaW1pdHMgPSBjKDAsbWF4RnJlcSksbGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSsKICB0aGVtZV9jbGFzc2ljKCkgKwogIGNvb3JkX2VxdWFsKCkgKwogIHRoZW1lKHN0cmlwLmJhY2tncm91bmQ9ZWxlbWVudF9ibGFuaygpLCBsZWdlbmQua2V5PWVsZW1lbnRfcmVjdChjb2xvcj1OQSksIGF4aXMubGluZT1lbGVtZW50X2JsYW5rKCksYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSxheGlzLnRpY2tzPWVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuYmFja2dyb3VuZD1lbGVtZW50X2JsYW5rKCkscGFuZWwuYm9yZGVyPWVsZW1lbnRfYmxhbmsoKSxwYW5lbC5ncmlkLm1ham9yPWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yPWVsZW1lbnRfYmxhbmsoKSxwbG90LmJhY2tncm91bmQ9ZWxlbWVudF9ibGFuaygpKSsKICBnZ3RpdGxlKCdTcGF0aWFsIEhlYXRtYXAnKQpoZWF0bWFwU3BhdGlhbAoKY29uY2VwdHVhbEhlYXRtYXAgPC0gZ2dwbG90KGNvbmNlcHRDb3VudHMsIGFlcyh4PVgsIHkgPSBZLCBmaWxsPVByb2IpKSArCiAgZ2VvbV90aWxlKCkrCiAgc2NhbGVfZmlsbF9kaXN0aWxsZXIocGFsZXR0ZSA9ICJTcGVjdHJhbCIsbmFtZSA9ICdGcmVxJywgdmFsdWVzPXJlc2NhbGUoYygwLDEvNjQsbWF4RnJlcSkpLCBsaW1pdHMgPSBjKDAsbWF4RnJlcSksbGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSsKICB0aGVtZV9jbGFzc2ljKCkgKwogIHhsYWIoJ1JvdGF0aW9uJykrCiAgeWxhYignU3RyaXBlcycpKwogIGNvb3JkX2VxdWFsKCkgKwogIHRoZW1lKHN0cmlwLmJhY2tncm91bmQ9ZWxlbWVudF9ibGFuaygpLCBsZWdlbmQua2V5PWVsZW1lbnRfcmVjdChjb2xvcj1OQSksIGF4aXMubGluZT1lbGVtZW50X2JsYW5rKCksYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSxheGlzLnRpY2tzPWVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuYmFja2dyb3VuZD1lbGVtZW50X2JsYW5rKCkscGFuZWwuYm9yZGVyPWVsZW1lbnRfYmxhbmsoKSxwYW5lbC5ncmlkLm1ham9yPWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yPWVsZW1lbnRfYmxhbmsoKSxwbG90LmJhY2tncm91bmQ9ZWxlbWVudF9ibGFuaygpKSsKICBnZ3RpdGxlKCdDb25jZXB0dWFsIEhlYXRtYXAnKQpjb25jZXB0dWFsSGVhdG1hcAoKYGBgCgojIyBSZWFjdGlvbiB0aW1lcwoKV2UgY2FuIGFsc28gYW5hbHl6ZSBwYXJ0aWNpcGFudCByZWFjdGlvbiB0aW1lcy4gUGFydGljaXBhbnRzIHdlcmUgc2xvd2VyIGluIHRoZSBjb25jZXB0dWFsIHRhc2sgKGByIHRmREYgPC0gZGRwbHkoZGYsIH5pZCtjb250ZXh0K2Vudmlyb25tZW50LCBwbHlyOjpzdW1tYXJpemUsIHRzID0gbWVhbih0cykpCnR0ZXN0UHJldHR5KGxvZyhzdWJzZXQodGZERiwgY29udGV4dCA9PSAnQ29uY2VwdHVhbCcpJHRzKSwgbG9nKHN1YnNldCh0ZkRGLCBjb250ZXh0ID09ICdTcGF0aWFsJykkdHMpLCBwYWlyZWQ9VClgKSwgYnV0IHRoZXJlIHdlcmUgbm8gZGlmZmVyZW5jZXMgYWNyb3NzIGVudmlyb25tZW50cyAoYHIgdGZERiA8LSBkZHBseShkZiwgfmlkK2NvbnRleHQrZW52aXJvbm1lbnQsIHBseXI6OnN1bW1hcml6ZSwgdHMgPSBtZWFuKHRzKSkKdHRlc3RQcmV0dHkobG9nKHN1YnNldCh0ZkRGLCBlbnZpcm9ubWVudCA9PSAnU21vb3RoJykkdHMpLCBsb2coc3Vic2V0KHRmREYsIGVudmlyb25tZW50ID09ICdSb3VnaCcpJHRzKSlgKS4KCgoKYGBge3J9CiNJbmRpdmlkdWFsIHBhcnRpY2lwYW50IHF1YXJ0aWxlIHNwbGl0cwpkZiRwcmV2UmV3YXJkVmFsdWUgPC0gTkEKZm9yIChwaWQgaW4gdW5pcXVlKGRmJGlkKSl7CiAgc3ViZCA8LSBzdWJzZXQoZGYsIGlkPT1waWQpCiAgeHMgPC0gcXVhbnRpbGUoc3ViZCRwcmV2aW91c1Jld2FyZCwgcHJvYnM9MDo0LzQsIG5hLnJtID0gVCkKICBkZltkZiRpZD09cGlkLCdwcmV2UmV3YXJkVmFsdWUnXSA8LSBjdXQoc3ViZCRwcmV2aW91c1Jld2FyZCwgYnJlYWtzPXhzLGxhYmVscz1jKCJRMSIsICJRMiIsICJRMyIsICJRNCIpICkKfQoKZGYkcHJldlJld2FyZFZhbHVlIDwtIGZhY3RvcihkZiRwcmV2UmV3YXJkVmFsdWUpCmxldmVscyhkZiRwcmV2UmV3YXJkVmFsdWUpIDwtIGMoIlExIiwgIlEyIiwgIlEzIiwgIlE0IikKY29sZnVuYzwtY29sb3JSYW1wUGFsZXR0ZShjKCIjMEQwODg3RkYiLCAiI0NDNDY3OEZGIiwgIiNGMEY5MjFGRiIpKQpwMTEgPC0gZ2dwbG90KHN1YnNldChkZiwgdHM+MCAmICFpcy5uYShwcmV2UmV3YXJkVmFsdWUpKSwgYWVzKHg9dHMvMTAwMCwgeT1wcmV2UmV3YXJkVmFsdWUsIGZpbGwgPSBwcmV2UmV3YXJkVmFsdWUpKSsKICBnZW9tX2RlbnNpdHlfcmlkZ2VzKCkrCiAgeGxhYignUlQgaW4gc2Vjb25kcyAobG9nIHNjYWxlKScpKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjb2xmdW5jKDUpLCBuYW1lPSIiKSsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjb2xmdW5jKDUpLCBuYW1lPSIiKSsKICBzY2FsZV94X2xvZzEwKCkrCiAgYW5ub3RhdGlvbl9sb2d0aWNrcyhzaWRlcz0nYicpKwogIGZhY2V0X2dyaWQofmNvbnRleHQsIGxhYmVsbGVyID0gYXNfbGFiZWxsZXIoY29udGV4dExhYmVscykpKwogIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYygwLjEsNTApKSsKICB0aGVtZV9jbGFzc2ljKCkrCiAgc2NhbGVfeV9kaXNjcmV0ZShleHBhbmQgPSBjKDAuMDEsIDApKSsKICB0aGVtZShsZWdlbmQucG9zaXRpb249J25vbmUnLCBzdHJpcC5iYWNrZ3JvdW5kPWVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLmtleT1lbGVtZW50X3JlY3QoY29sb3I9TkEpKSsKICB5bGFiKCdQcmV2aW91cyBSZXdhcmQnKQpwMTEKYGBgCgpUaGVyZSBkb2Vzbid0IHNlZW0gdG8gYmUgYW55IGNvbm5lY3Rpb24gYmV0d2VlbiByZWFjdGlvbiB0aW1lIGFuZCBwcmV2aW91cyByZXdhcmQgdmFsdWUuIEl0IHNlZW1zIGxpa2UgYW55IGluZmx1ZW5jZSBvZiBkZWxpYmVyYXRpb24gb24gcmVhY3Rpb24gdGltZSBpcyBsaWtlbHkgd2FzaGVkIG91dCBieSBsYXJnZXIgaW5mbHVlbmNlIG9mIHRyYWplY3RvcnkgbGVuZ3RoLgoKYGBge3J9CmdncGxvdChzdWJzZXQoZGYsc3RlcHM8PTIwKSwgYWVzKHggPXN0ZXBzLCAgeSA9IGxvZyh0cy8xMDAwKSwgY29sb3IgPSBjb250ZXh0LCBmaWxsID0gY29udGV4dCkpKwogICNnZW9tX3Ntb290aChmaWxsPU5BKSsKICBzdGF0X3N1bW1hcnkoZnVuLnkgPSBtZWFuLCBnZW9tID0gInBvaW50IikgKyAKICBzdGF0X3N1bW1hcnkoZnVuLmRhdGEgPSBtZWFuX2NsX2Jvb3QsIGdlb20gPSAiZXJyb3JiYXIiKSArCiAgI2Nvb3JkX2NhcnRlc2lhbih4bGltPWMoMCwyMCksIHlsaW09Yyg0LDEwKSkgKyAjVHVrZXkgb3V0bGllciBjcml0ZXJpb24gaW5kaWNhdGVzIG91dGxpZXJzIGFib3ZlIDIwOyBtaW4oYm94cGxvdC5zdGF0cyhkZiRzdGVwcykkb3V0KQogICNmYWNldF9ncmlkKH5lbnZpcm9ubWVudCkrCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJEYXJrMiIsIG5hbWU9IlRhc2siKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiLCBuYW1lPSJUYXNrIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj1jKDAuMDUsMSksbGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDAsMSksIHN0cmlwLmJhY2tncm91bmQ9ZWxlbWVudF9ibGFuaygpLCBsZWdlbmQuYmFja2dyb3VuZD1lbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5rZXk9ZWxlbWVudF9yZWN0KGNvbG9yPU5BKSkrCiAgeWxhYigiUlQgaW4gc2Vjb25kcyAobG9nIHNjYWxlKSIpKwogIHhsYWIoJ1RyYWplY3RvcnkgTGVuZ3RoJykrCiAgc2NhbGVfeV9sb2cxMCgpKwogIGFubm90YXRpb25fbG9ndGlja3Moc2lkZXM9J2wnKQoKYGBgCgojIEZpbmFsIFBsb3RzCiMjIE1haW4gdGV4dAoKYGBge3IgZmlnLmhlaWdodCA9IDcsIGZpZy53aWR0aCA9IDl9CiNjb21wbGV0ZXBsb3QgPC0gcGxvdF9ncmlkKHAzYSwgcDFiLCBwNGFsdCwgdHJhamVjdG9yeXBsb3QsIHBHZW5lcmFsaXphdGlvbiwgcDUsY29uY2VwdHVhbEhlYXRtYXAsIGhlYXRtYXBTcGF0aWFsICwgbmNvbD0yLCBsYWJlbHMgPSAiYXV0byIpCmNvbXBsZXRlcGxvdCA8LSBjb3dwbG90OjpwbG90X2dyaWQocDFhLCBwMWIsIHBPcmRlciAscDNhLCAgcDRhbHQsIHA1YWx0LCBuY29sPTIsIGxhYmVscyA9ICJhdXRvIikKY29tcGxldGVwbG90CgpnZ3NhdmUoJy4uL3Bsb3RzL2JlaGF2aW9yYWxwbG90LnBkZicsY29tcGxldGVwbG90LCB3aWR0aCA9IDEwLCBoZWlnaHQgPSA4LCB1bml0PSdpbicsIHVzZURpbmdiYXRzPUYpCmBgYAojIyBTSQoKYGBge3IgZmlnLndpZHRoID0gMTIsIGZpZy5oZWlnaHQgPSA0fQoKI1NJIHBsb3RzCnRyYWluaW5nUm91bmQgPC0gY293cGxvdDo6cGxvdF9ncmlkKHRyYWpDb21wbGV0ZSwgdHJhanAxYSwgdHJhamhlYXRtYXAsIHBFcnJvciwgIG5jb2w9MiwgbGFiZWxzID0gJ2F1dG8nKQp0cmFpbmluZ1JvdW5kCmdnc2F2ZShmaWxlbmFtZSA9ICcuLi9wbG90cy9UcmFpbmluZ1Bsb3RzLnBkZicsIHRyYWluaW5nUm91bmQsIHdpZHRoID0gOSxoZWlnaHQgPSA2LCB1bml0cyA9ICdpbicsIHVzZURpbmdiYXRzPUZBTFNFKQoKCmBgYAoKYGBge3IgZmlnLndpZHRoID0gMTIsIGZpZy5oZWlnaHQgPSA0fQp0cmFqZWN0b3J5UGxvdHMgPC0gY293cGxvdDo6cGxvdF9ncmlkKHRyYWplY3RvcnlwbG90LHBUcmFqTGVuZ3RoUmV3YXJkLHA2LCBpbnB1dGRpcixwQXR0ZW50aW9uVGFza09yZGVyLCBwU2NvcmVBdHRlbnRpb24sICBuY29sPTMsIGxhYmVscz0iYXV0byIpCnRyYWplY3RvcnlQbG90cwpnZ3NhdmUoZmlsZW5hbWUgPSAnLi4vcGxvdHMvVHJhamVjdG9yeVBsb3RzLnBkZicsIHRyYWplY3RvcnlQbG90cywgd2lkdGggPSAxMixoZWlnaHQgPSA2LCB1bml0cyA9ICdpbicsIHVzZURpbmdiYXRzPUZBTFNFKQoKCmBgYAoKYGBge3IgZmlnLndpZHRoID0gOCwgZmlnLmhlaWdodCA9IDR9CgpoZWF0bWFwcyA8LSBjb3dwbG90OjpwbG90X2dyaWQoY29uY2VwdHVhbEhlYXRtYXAsIGhlYXRtYXBTcGF0aWFsLCBsYWJlbHMgPSAiYXV0byIpCmhlYXRtYXBzCmdnc2F2ZShmaWxlbmFtZSA9ICcuLi9wbG90cy9oZWF0bWFwcy5wZGYnLCBoZWF0bWFwcywgd2lkdGggPSA4LGhlaWdodCA9IDQsIHVuaXRzID0gJ2luJywgdXNlRGluZ2JhdHM9RkFMU0UpCmBgYAoK